changeset 20654:3a585a964542 draft

contrib: import elftoolchain from FreeBSD
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Fri, 30 Nov 2018 12:49:04 -0500
parents cbdda82385e8
children a1344b5e7511 fac86a462efb
files contrib/elftoolchain/addr2line/Makefile contrib/elftoolchain/addr2line/addr2line.1 contrib/elftoolchain/addr2line/addr2line.c contrib/elftoolchain/addr2line/os.NetBSD.mk contrib/elftoolchain/ar/Makefile contrib/elftoolchain/ar/acplex.l contrib/elftoolchain/ar/acpyacc.y contrib/elftoolchain/ar/ar.1 contrib/elftoolchain/ar/ar.5 contrib/elftoolchain/ar/ar.c contrib/elftoolchain/ar/ar.h contrib/elftoolchain/ar/benchmark/acp.sh contrib/elftoolchain/ar/os.FreeBSD.mk contrib/elftoolchain/ar/os.Linux.mk contrib/elftoolchain/ar/ranlib.1 contrib/elftoolchain/ar/read.c contrib/elftoolchain/ar/util.c contrib/elftoolchain/ar/write.c contrib/elftoolchain/brandelf/Makefile contrib/elftoolchain/brandelf/brandelf.1 contrib/elftoolchain/brandelf/brandelf.c contrib/elftoolchain/common/Makefile contrib/elftoolchain/common/_elftc.h contrib/elftoolchain/common/elfdefinitions.h contrib/elftoolchain/common/native-elf-format contrib/elftoolchain/common/os.Linux.mk contrib/elftoolchain/common/utarray.h contrib/elftoolchain/common/uthash.h contrib/elftoolchain/cxxfilt/Makefile contrib/elftoolchain/cxxfilt/c++filt.1 contrib/elftoolchain/cxxfilt/cxxfilt.c contrib/elftoolchain/elfcopy/Makefile contrib/elftoolchain/elfcopy/archive.c contrib/elftoolchain/elfcopy/ascii.c contrib/elftoolchain/elfcopy/binary.c contrib/elftoolchain/elfcopy/elfcopy.1 contrib/elftoolchain/elfcopy/elfcopy.h contrib/elftoolchain/elfcopy/main.c contrib/elftoolchain/elfcopy/mcs.1 contrib/elftoolchain/elfcopy/os.FreeBSD.mk contrib/elftoolchain/elfcopy/pe.c contrib/elftoolchain/elfcopy/sections.c contrib/elftoolchain/elfcopy/segments.c contrib/elftoolchain/elfcopy/strip.1 contrib/elftoolchain/elfcopy/symbols.c contrib/elftoolchain/elfdump/Makefile contrib/elftoolchain/elfdump/elfdump.1 contrib/elftoolchain/elfdump/elfdump.c contrib/elftoolchain/elfdump/os.NetBSD.mk contrib/elftoolchain/libdwarf/Makefile contrib/elftoolchain/libdwarf/Version.map contrib/elftoolchain/libdwarf/_libdwarf.h contrib/elftoolchain/libdwarf/dwarf.3 contrib/elftoolchain/libdwarf/dwarf.h contrib/elftoolchain/libdwarf/dwarf_abbrev.c contrib/elftoolchain/libdwarf/dwarf_add_AT_comp_dir.3 contrib/elftoolchain/libdwarf/dwarf_add_AT_const_value_string.3 contrib/elftoolchain/libdwarf/dwarf_add_AT_dataref.3 contrib/elftoolchain/libdwarf/dwarf_add_AT_flag.3 contrib/elftoolchain/libdwarf/dwarf_add_AT_location_expr.3 contrib/elftoolchain/libdwarf/dwarf_add_AT_name.3 contrib/elftoolchain/libdwarf/dwarf_add_AT_producer.3 contrib/elftoolchain/libdwarf/dwarf_add_AT_ref_address.3 contrib/elftoolchain/libdwarf/dwarf_add_AT_reference.3 contrib/elftoolchain/libdwarf/dwarf_add_AT_signed_const.3 contrib/elftoolchain/libdwarf/dwarf_add_AT_string.3 contrib/elftoolchain/libdwarf/dwarf_add_AT_targ_address.3 contrib/elftoolchain/libdwarf/dwarf_add_arange.3 contrib/elftoolchain/libdwarf/dwarf_add_die_to_debug.3 contrib/elftoolchain/libdwarf/dwarf_add_directory_decl.3 contrib/elftoolchain/libdwarf/dwarf_add_expr_addr.3 contrib/elftoolchain/libdwarf/dwarf_add_expr_gen.3 contrib/elftoolchain/libdwarf/dwarf_add_fde_inst.3 contrib/elftoolchain/libdwarf/dwarf_add_file_decl.3 contrib/elftoolchain/libdwarf/dwarf_add_frame_cie.3 contrib/elftoolchain/libdwarf/dwarf_add_frame_fde.3 contrib/elftoolchain/libdwarf/dwarf_add_funcname.3 contrib/elftoolchain/libdwarf/dwarf_add_line_entry.3 contrib/elftoolchain/libdwarf/dwarf_add_pubname.3 contrib/elftoolchain/libdwarf/dwarf_add_typename.3 contrib/elftoolchain/libdwarf/dwarf_add_varname.3 contrib/elftoolchain/libdwarf/dwarf_add_weakname.3 contrib/elftoolchain/libdwarf/dwarf_arange.c contrib/elftoolchain/libdwarf/dwarf_attr.3 contrib/elftoolchain/libdwarf/dwarf_attr.c contrib/elftoolchain/libdwarf/dwarf_attrlist.3 contrib/elftoolchain/libdwarf/dwarf_attroffset.3 contrib/elftoolchain/libdwarf/dwarf_attrval.c contrib/elftoolchain/libdwarf/dwarf_attrval_signed.3 contrib/elftoolchain/libdwarf/dwarf_child.3 contrib/elftoolchain/libdwarf/dwarf_cu.c contrib/elftoolchain/libdwarf/dwarf_dealloc.3 contrib/elftoolchain/libdwarf/dwarf_dealloc.c contrib/elftoolchain/libdwarf/dwarf_def_macro.3 contrib/elftoolchain/libdwarf/dwarf_die.c contrib/elftoolchain/libdwarf/dwarf_die_abbrev_code.3 contrib/elftoolchain/libdwarf/dwarf_die_link.3 contrib/elftoolchain/libdwarf/dwarf_diename.3 contrib/elftoolchain/libdwarf/dwarf_dieoffset.3 contrib/elftoolchain/libdwarf/dwarf_dump.c contrib/elftoolchain/libdwarf/dwarf_end_macro_file.3 contrib/elftoolchain/libdwarf/dwarf_errmsg.3 contrib/elftoolchain/libdwarf/dwarf_errmsg.c contrib/elftoolchain/libdwarf/dwarf_errno.3 contrib/elftoolchain/libdwarf/dwarf_expand_frame_instructions.3 contrib/elftoolchain/libdwarf/dwarf_expr_current_offset.3 contrib/elftoolchain/libdwarf/dwarf_expr_into_block.3 contrib/elftoolchain/libdwarf/dwarf_fde_cfa_offset.3 contrib/elftoolchain/libdwarf/dwarf_find_macro_value_start.3 contrib/elftoolchain/libdwarf/dwarf_finish.3 contrib/elftoolchain/libdwarf/dwarf_finish.c contrib/elftoolchain/libdwarf/dwarf_form.c contrib/elftoolchain/libdwarf/dwarf_formaddr.3 contrib/elftoolchain/libdwarf/dwarf_formblock.3 contrib/elftoolchain/libdwarf/dwarf_formexprloc.3 contrib/elftoolchain/libdwarf/dwarf_formflag.3 contrib/elftoolchain/libdwarf/dwarf_formref.3 contrib/elftoolchain/libdwarf/dwarf_formsig8.3 contrib/elftoolchain/libdwarf/dwarf_formstring.3 contrib/elftoolchain/libdwarf/dwarf_formudata.3 contrib/elftoolchain/libdwarf/dwarf_frame.c contrib/elftoolchain/libdwarf/dwarf_funcs.m4 contrib/elftoolchain/libdwarf/dwarf_get_AT_name.3 contrib/elftoolchain/libdwarf/dwarf_get_abbrev.3 contrib/elftoolchain/libdwarf/dwarf_get_abbrev_children_flag.3 contrib/elftoolchain/libdwarf/dwarf_get_abbrev_code.3 contrib/elftoolchain/libdwarf/dwarf_get_abbrev_entry.3 contrib/elftoolchain/libdwarf/dwarf_get_abbrev_tag.3 contrib/elftoolchain/libdwarf/dwarf_get_address_size.3 contrib/elftoolchain/libdwarf/dwarf_get_arange.3 contrib/elftoolchain/libdwarf/dwarf_get_arange_info.3 contrib/elftoolchain/libdwarf/dwarf_get_aranges.3 contrib/elftoolchain/libdwarf/dwarf_get_cie_index.3 contrib/elftoolchain/libdwarf/dwarf_get_cie_info.3 contrib/elftoolchain/libdwarf/dwarf_get_cie_of_fde.3 contrib/elftoolchain/libdwarf/dwarf_get_cu_die_offset.3 contrib/elftoolchain/libdwarf/dwarf_get_die_infotypes_flag.3 contrib/elftoolchain/libdwarf/dwarf_get_elf.3 contrib/elftoolchain/libdwarf/dwarf_get_fde_at_pc.3 contrib/elftoolchain/libdwarf/dwarf_get_fde_info_for_all_regs.3 contrib/elftoolchain/libdwarf/dwarf_get_fde_info_for_all_regs3.3 contrib/elftoolchain/libdwarf/dwarf_get_fde_info_for_cfa_reg3.3 contrib/elftoolchain/libdwarf/dwarf_get_fde_info_for_reg.3 contrib/elftoolchain/libdwarf/dwarf_get_fde_info_for_reg3.3 contrib/elftoolchain/libdwarf/dwarf_get_fde_instr_bytes.3 contrib/elftoolchain/libdwarf/dwarf_get_fde_list.3 contrib/elftoolchain/libdwarf/dwarf_get_fde_n.3 contrib/elftoolchain/libdwarf/dwarf_get_fde_range.3 contrib/elftoolchain/libdwarf/dwarf_get_form_class.3 contrib/elftoolchain/libdwarf/dwarf_get_funcs.3 contrib/elftoolchain/libdwarf/dwarf_get_globals.3 contrib/elftoolchain/libdwarf/dwarf_get_loclist_entry.3 contrib/elftoolchain/libdwarf/dwarf_get_macro_details.3 contrib/elftoolchain/libdwarf/dwarf_get_pubtypes.3 contrib/elftoolchain/libdwarf/dwarf_get_ranges.3 contrib/elftoolchain/libdwarf/dwarf_get_relocation_info.3 contrib/elftoolchain/libdwarf/dwarf_get_relocation_info_count.3 contrib/elftoolchain/libdwarf/dwarf_get_section_bytes.3 contrib/elftoolchain/libdwarf/dwarf_get_section_max_offsets.3 contrib/elftoolchain/libdwarf/dwarf_get_str.3 contrib/elftoolchain/libdwarf/dwarf_get_types.3 contrib/elftoolchain/libdwarf/dwarf_get_vars.3 contrib/elftoolchain/libdwarf/dwarf_get_weaks.3 contrib/elftoolchain/libdwarf/dwarf_hasattr.3 contrib/elftoolchain/libdwarf/dwarf_hasform.3 contrib/elftoolchain/libdwarf/dwarf_highpc.3 contrib/elftoolchain/libdwarf/dwarf_init.3 contrib/elftoolchain/libdwarf/dwarf_init.c contrib/elftoolchain/libdwarf/dwarf_lineno.3 contrib/elftoolchain/libdwarf/dwarf_lineno.c contrib/elftoolchain/libdwarf/dwarf_lne_end_sequence.3 contrib/elftoolchain/libdwarf/dwarf_lne_set_address.3 contrib/elftoolchain/libdwarf/dwarf_loclist.3 contrib/elftoolchain/libdwarf/dwarf_loclist.c contrib/elftoolchain/libdwarf/dwarf_loclist_from_expr.3 contrib/elftoolchain/libdwarf/dwarf_macinfo.c contrib/elftoolchain/libdwarf/dwarf_nametbl.m4 contrib/elftoolchain/libdwarf/dwarf_new_die.3 contrib/elftoolchain/libdwarf/dwarf_new_expr.3 contrib/elftoolchain/libdwarf/dwarf_new_fde.3 contrib/elftoolchain/libdwarf/dwarf_next_cu_header.3 contrib/elftoolchain/libdwarf/dwarf_next_types_section.3 contrib/elftoolchain/libdwarf/dwarf_object_init.3 contrib/elftoolchain/libdwarf/dwarf_pro_arange.c contrib/elftoolchain/libdwarf/dwarf_pro_attr.c contrib/elftoolchain/libdwarf/dwarf_pro_die.c contrib/elftoolchain/libdwarf/dwarf_pro_expr.c contrib/elftoolchain/libdwarf/dwarf_pro_finish.c contrib/elftoolchain/libdwarf/dwarf_pro_frame.c contrib/elftoolchain/libdwarf/dwarf_pro_funcs.m4 contrib/elftoolchain/libdwarf/dwarf_pro_init.c contrib/elftoolchain/libdwarf/dwarf_pro_lineno.c contrib/elftoolchain/libdwarf/dwarf_pro_macinfo.c contrib/elftoolchain/libdwarf/dwarf_pro_nametbl.m4 contrib/elftoolchain/libdwarf/dwarf_pro_pubnames.m4 contrib/elftoolchain/libdwarf/dwarf_pro_reloc.c contrib/elftoolchain/libdwarf/dwarf_pro_sections.c contrib/elftoolchain/libdwarf/dwarf_pro_types.m4 contrib/elftoolchain/libdwarf/dwarf_pro_vars.m4 contrib/elftoolchain/libdwarf/dwarf_pro_weaks.m4 contrib/elftoolchain/libdwarf/dwarf_producer_init.3 contrib/elftoolchain/libdwarf/dwarf_producer_set_isa.3 contrib/elftoolchain/libdwarf/dwarf_pubnames.m4 contrib/elftoolchain/libdwarf/dwarf_pubtypes.m4 contrib/elftoolchain/libdwarf/dwarf_ranges.c contrib/elftoolchain/libdwarf/dwarf_reloc.c contrib/elftoolchain/libdwarf/dwarf_reset_section_bytes.3 contrib/elftoolchain/libdwarf/dwarf_sections.c contrib/elftoolchain/libdwarf/dwarf_set_frame_cfa_value.3 contrib/elftoolchain/libdwarf/dwarf_set_reloc_application.3 contrib/elftoolchain/libdwarf/dwarf_seterrarg.3 contrib/elftoolchain/libdwarf/dwarf_seterror.c contrib/elftoolchain/libdwarf/dwarf_srcfiles.3 contrib/elftoolchain/libdwarf/dwarf_srclines.3 contrib/elftoolchain/libdwarf/dwarf_start_macro_file.3 contrib/elftoolchain/libdwarf/dwarf_str.c contrib/elftoolchain/libdwarf/dwarf_tag.3 contrib/elftoolchain/libdwarf/dwarf_transform_to_disk_form.3 contrib/elftoolchain/libdwarf/dwarf_types.m4 contrib/elftoolchain/libdwarf/dwarf_undef_macro.3 contrib/elftoolchain/libdwarf/dwarf_vars.m4 contrib/elftoolchain/libdwarf/dwarf_vendor_ext.3 contrib/elftoolchain/libdwarf/dwarf_weaks.m4 contrib/elftoolchain/libdwarf/dwarf_whatattr.3 contrib/elftoolchain/libdwarf/libdwarf.c contrib/elftoolchain/libdwarf/libdwarf.h contrib/elftoolchain/libdwarf/libdwarf_abbrev.c contrib/elftoolchain/libdwarf/libdwarf_arange.c contrib/elftoolchain/libdwarf/libdwarf_attr.c contrib/elftoolchain/libdwarf/libdwarf_die.c contrib/elftoolchain/libdwarf/libdwarf_elf_access.c contrib/elftoolchain/libdwarf/libdwarf_elf_init.c contrib/elftoolchain/libdwarf/libdwarf_error.c contrib/elftoolchain/libdwarf/libdwarf_frame.c contrib/elftoolchain/libdwarf/libdwarf_info.c contrib/elftoolchain/libdwarf/libdwarf_init.c contrib/elftoolchain/libdwarf/libdwarf_lineno.c contrib/elftoolchain/libdwarf/libdwarf_loc.c contrib/elftoolchain/libdwarf/libdwarf_loclist.c contrib/elftoolchain/libdwarf/libdwarf_macinfo.c contrib/elftoolchain/libdwarf/libdwarf_nametbl.c contrib/elftoolchain/libdwarf/libdwarf_ranges.c contrib/elftoolchain/libdwarf/libdwarf_reloc.c contrib/elftoolchain/libdwarf/libdwarf_rw.c contrib/elftoolchain/libdwarf/libdwarf_sections.c contrib/elftoolchain/libdwarf/libdwarf_str.c contrib/elftoolchain/libdwarf/os.NetBSD.mk contrib/elftoolchain/libelf/Makefile contrib/elftoolchain/libelf/Version.map contrib/elftoolchain/libelf/_libelf.h contrib/elftoolchain/libelf/_libelf_ar.h contrib/elftoolchain/libelf/_libelf_config.h contrib/elftoolchain/libelf/elf.3 contrib/elftoolchain/libelf/elf.c contrib/elftoolchain/libelf/elf_begin.3 contrib/elftoolchain/libelf/elf_begin.c contrib/elftoolchain/libelf/elf_cntl.3 contrib/elftoolchain/libelf/elf_cntl.c contrib/elftoolchain/libelf/elf_data.c contrib/elftoolchain/libelf/elf_end.3 contrib/elftoolchain/libelf/elf_end.c contrib/elftoolchain/libelf/elf_errmsg.3 contrib/elftoolchain/libelf/elf_errmsg.c contrib/elftoolchain/libelf/elf_errno.c contrib/elftoolchain/libelf/elf_fill.3 contrib/elftoolchain/libelf/elf_fill.c contrib/elftoolchain/libelf/elf_flag.c contrib/elftoolchain/libelf/elf_flagdata.3 contrib/elftoolchain/libelf/elf_getarhdr.3 contrib/elftoolchain/libelf/elf_getarhdr.c contrib/elftoolchain/libelf/elf_getarsym.3 contrib/elftoolchain/libelf/elf_getarsym.c contrib/elftoolchain/libelf/elf_getbase.3 contrib/elftoolchain/libelf/elf_getbase.c contrib/elftoolchain/libelf/elf_getdata.3 contrib/elftoolchain/libelf/elf_getident.3 contrib/elftoolchain/libelf/elf_getident.c contrib/elftoolchain/libelf/elf_getphdrnum.3 contrib/elftoolchain/libelf/elf_getphnum.3 contrib/elftoolchain/libelf/elf_getscn.3 contrib/elftoolchain/libelf/elf_getshdrnum.3 contrib/elftoolchain/libelf/elf_getshdrstrndx.3 contrib/elftoolchain/libelf/elf_getshnum.3 contrib/elftoolchain/libelf/elf_getshstrndx.3 contrib/elftoolchain/libelf/elf_hash.3 contrib/elftoolchain/libelf/elf_hash.c contrib/elftoolchain/libelf/elf_kind.3 contrib/elftoolchain/libelf/elf_kind.c contrib/elftoolchain/libelf/elf_memory.3 contrib/elftoolchain/libelf/elf_memory.c contrib/elftoolchain/libelf/elf_next.3 contrib/elftoolchain/libelf/elf_next.c contrib/elftoolchain/libelf/elf_open.3 contrib/elftoolchain/libelf/elf_open.c contrib/elftoolchain/libelf/elf_phnum.c contrib/elftoolchain/libelf/elf_rand.3 contrib/elftoolchain/libelf/elf_rand.c contrib/elftoolchain/libelf/elf_rawfile.3 contrib/elftoolchain/libelf/elf_rawfile.c contrib/elftoolchain/libelf/elf_scn.c contrib/elftoolchain/libelf/elf_shnum.c contrib/elftoolchain/libelf/elf_shstrndx.c contrib/elftoolchain/libelf/elf_strptr.3 contrib/elftoolchain/libelf/elf_strptr.c contrib/elftoolchain/libelf/elf_types.m4 contrib/elftoolchain/libelf/elf_update.3 contrib/elftoolchain/libelf/elf_update.c contrib/elftoolchain/libelf/elf_version.3 contrib/elftoolchain/libelf/elf_version.c contrib/elftoolchain/libelf/gelf.3 contrib/elftoolchain/libelf/gelf.h contrib/elftoolchain/libelf/gelf_cap.c contrib/elftoolchain/libelf/gelf_checksum.3 contrib/elftoolchain/libelf/gelf_checksum.c contrib/elftoolchain/libelf/gelf_dyn.c contrib/elftoolchain/libelf/gelf_ehdr.c contrib/elftoolchain/libelf/gelf_fsize.3 contrib/elftoolchain/libelf/gelf_fsize.c contrib/elftoolchain/libelf/gelf_getcap.3 contrib/elftoolchain/libelf/gelf_getclass.3 contrib/elftoolchain/libelf/gelf_getclass.c contrib/elftoolchain/libelf/gelf_getdyn.3 contrib/elftoolchain/libelf/gelf_getehdr.3 contrib/elftoolchain/libelf/gelf_getmove.3 contrib/elftoolchain/libelf/gelf_getphdr.3 contrib/elftoolchain/libelf/gelf_getrel.3 contrib/elftoolchain/libelf/gelf_getrela.3 contrib/elftoolchain/libelf/gelf_getshdr.3 contrib/elftoolchain/libelf/gelf_getsym.3 contrib/elftoolchain/libelf/gelf_getsyminfo.3 contrib/elftoolchain/libelf/gelf_getsymshndx.3 contrib/elftoolchain/libelf/gelf_mips64el.c contrib/elftoolchain/libelf/gelf_move.c contrib/elftoolchain/libelf/gelf_newehdr.3 contrib/elftoolchain/libelf/gelf_newphdr.3 contrib/elftoolchain/libelf/gelf_phdr.c contrib/elftoolchain/libelf/gelf_rel.c contrib/elftoolchain/libelf/gelf_rela.c contrib/elftoolchain/libelf/gelf_shdr.c contrib/elftoolchain/libelf/gelf_sym.c contrib/elftoolchain/libelf/gelf_syminfo.c contrib/elftoolchain/libelf/gelf_symshndx.c contrib/elftoolchain/libelf/gelf_update_ehdr.3 contrib/elftoolchain/libelf/gelf_xlate.c contrib/elftoolchain/libelf/gelf_xlatetof.3 contrib/elftoolchain/libelf/libelf.h contrib/elftoolchain/libelf/libelf_align.c contrib/elftoolchain/libelf/libelf_allocate.c contrib/elftoolchain/libelf/libelf_ar.c contrib/elftoolchain/libelf/libelf_ar_util.c contrib/elftoolchain/libelf/libelf_checksum.c contrib/elftoolchain/libelf/libelf_convert.m4 contrib/elftoolchain/libelf/libelf_data.c contrib/elftoolchain/libelf/libelf_ehdr.c contrib/elftoolchain/libelf/libelf_extended.c contrib/elftoolchain/libelf/libelf_fsize.m4 contrib/elftoolchain/libelf/libelf_memory.c contrib/elftoolchain/libelf/libelf_msize.m4 contrib/elftoolchain/libelf/libelf_open.c contrib/elftoolchain/libelf/libelf_phdr.c contrib/elftoolchain/libelf/libelf_shdr.c contrib/elftoolchain/libelf/libelf_xlate.c contrib/elftoolchain/libelf/os.FreeBSD.mk contrib/elftoolchain/libelf/os.NetBSD.mk contrib/elftoolchain/libelftc/Makefile contrib/elftoolchain/libelftc/Version.map contrib/elftoolchain/libelftc/_libelftc.h contrib/elftoolchain/libelftc/elftc.3 contrib/elftoolchain/libelftc/elftc_bfd_find_target.3 contrib/elftoolchain/libelftc/elftc_bfdtarget.c contrib/elftoolchain/libelftc/elftc_copyfile.3 contrib/elftoolchain/libelftc/elftc_copyfile.c contrib/elftoolchain/libelftc/elftc_demangle.3 contrib/elftoolchain/libelftc/elftc_demangle.c contrib/elftoolchain/libelftc/elftc_reloc_type_str.3 contrib/elftoolchain/libelftc/elftc_reloc_type_str.c contrib/elftoolchain/libelftc/elftc_set_timestamps.3 contrib/elftoolchain/libelftc/elftc_set_timestamps.c contrib/elftoolchain/libelftc/elftc_string_table.c contrib/elftoolchain/libelftc/elftc_string_table_create.3 contrib/elftoolchain/libelftc/elftc_timestamp.3 contrib/elftoolchain/libelftc/elftc_timestamp.c contrib/elftoolchain/libelftc/elftc_version.3 contrib/elftoolchain/libelftc/libelftc.h contrib/elftoolchain/libelftc/libelftc_bfdtarget.c contrib/elftoolchain/libelftc/libelftc_dem_arm.c contrib/elftoolchain/libelftc/libelftc_dem_gnu2.c contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c contrib/elftoolchain/libelftc/libelftc_hash.c contrib/elftoolchain/libelftc/libelftc_vstr.c contrib/elftoolchain/libelftc/make-toolchain-version contrib/elftoolchain/libelftc/os.FreeBSD.mk contrib/elftoolchain/libelftc/os.Linux.mk contrib/elftoolchain/libelftc/os.NetBSD.mk contrib/elftoolchain/libpe/Makefile contrib/elftoolchain/libpe/_libpe.h contrib/elftoolchain/libpe/libpe.h contrib/elftoolchain/libpe/libpe_buffer.c contrib/elftoolchain/libpe/libpe_coff.c contrib/elftoolchain/libpe/libpe_dos.c contrib/elftoolchain/libpe/libpe_init.c contrib/elftoolchain/libpe/libpe_rich.c contrib/elftoolchain/libpe/libpe_section.c contrib/elftoolchain/libpe/libpe_utils.c contrib/elftoolchain/libpe/os.Linux.mk contrib/elftoolchain/libpe/os.NetBSD.mk contrib/elftoolchain/libpe/pe.h contrib/elftoolchain/libpe/pe_buffer.c contrib/elftoolchain/libpe/pe_cntl.c contrib/elftoolchain/libpe/pe_coff.c contrib/elftoolchain/libpe/pe_dos.c contrib/elftoolchain/libpe/pe_flag.c contrib/elftoolchain/libpe/pe_init.c contrib/elftoolchain/libpe/pe_rich.c contrib/elftoolchain/libpe/pe_section.c contrib/elftoolchain/libpe/pe_symtab.c contrib/elftoolchain/libpe/pe_update.c contrib/elftoolchain/nm/Makefile contrib/elftoolchain/nm/nm.1 contrib/elftoolchain/nm/nm.c contrib/elftoolchain/nm/os.NetBSD.mk contrib/elftoolchain/readelf/Makefile contrib/elftoolchain/readelf/os.NetBSD.mk contrib/elftoolchain/readelf/readelf.1 contrib/elftoolchain/readelf/readelf.c contrib/elftoolchain/size/Makefile contrib/elftoolchain/size/os.NetBSD.mk contrib/elftoolchain/size/size.1 contrib/elftoolchain/size/size.c contrib/elftoolchain/strings/Makefile contrib/elftoolchain/strings/os.NetBSD.mk contrib/elftoolchain/strings/strings.1 contrib/elftoolchain/strings/strings.c contrib/elftoolchain/upstream-version
diffstat 434 files changed, 101336 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/addr2line/Makefile	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,15 @@
+# $Id: Makefile 2066 2011-10-26 15:40:28Z jkoshy $
+
+TOP=	..
+
+PROG=	addr2line
+SRCS=	addr2line.c
+
+WARNS?=	6
+
+DPADD=	${LIBELF} ${LIBELFTC} ${LIBDWARF}
+LDADD=	-lelftc -ldwarf -lelf
+
+MAN1=	addr2line.1
+
+.include "${TOP}/mk/elftoolchain.prog.mk"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/addr2line/addr2line.1	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,182 @@
+.\" Copyright (c) 2009,2010 Joseph Koshy <jkoshy@users.sourceforge.net>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer
+.\"    in this position and unchanged.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $Id: addr2line.1 3263 2015-11-30 04:25:54Z kaiwang27 $
+.\"
+.Dd November 30, 2015
+.Os
+.Dt ADDR2LINE 1
+.Sh NAME
+.Nm addr2line
+.Nd translate program addresses to source file names and line numbers
+.Sh SYNOPSIS
+.Nm
+.Op Fl a | Fl -addresses
+.Op Fl b Ar target | Fl -target Ns = Ns Ar target
+.Op Fl e Ar pathname | Fl -exe Ns = Ns Ar pathname
+.Op Fl f | Fl -functions
+.Op Fl i | Fl -inlines
+.Op Fl j Ar sectionname | Fl -section Ns = Ns Ar sectionname
+.Op Fl p | Fl -pretty-print
+.Op Fl s | Fl -basename
+.Op Fl C | Fl -demangle
+.Op Fl H | Fl -help
+.Op Fl V | Fl -version
+.Op Ar hexaddress Ns ...
+.Sh DESCRIPTION
+The
+.Nm
+utility translates program addresses specified by the command line
+arguments
+.Ar hexaddress
+to their corresponding source file names and line numbers.
+If no arguments are given to
+.Nm ,
+it will read these addresses from standard input.
+.Pp
+Program addresses specified by arguments
+.Ar hexaddress
+are encoded using the conventions accepted by
+.Xr strtoull 3 .
+.Pp
+By default,
+.Nm
+will use the executable
+.Dq Pa a.out .
+The
+.Fl e
+option may be used to specified a different ELF object.
+.Pp
+The
+.Nm
+utility recognizes the following options:
+.Bl -tag -width indent
+.It Fl a | Fl -addresses
+Display the address prior to the line number information.
+.It Fl b Ar target | Fl -target Ns = Ns Ar target
+This option is recognized by
+.Nm
+but is ignored.
+It is supported for compatibility with GNU binutils.
+.It Fl e Ar pathname | Fl -exe Ns = Ns Ar pathname
+Use the ELF object specified by argument
+.Ar pathname
+to translate addresses.
+If this option is not specified,
+.Nm
+will use the file
+.Dq Pa a.out .
+.It Fl f | Fl -functions
+Display function names in addition to file and line number information.
+.It Fl i | Fl -inlines
+If the address specified belongs to an inlined function, also display the line
+number information for its caller, recursively until the first non-inlined
+caller.
+.It Fl j Ar sectionname | Fl -section Ns = Ns Ar sectionname
+The values specified by arguments
+.Ar hexaddress
+are to be treated as offsets into the section named
+.Ar sectionname .
+.It Fl p | -pretty-print
+Display the line number information on one line, in human readable manner.
+.It Fl s | -basename
+Display only the base name for each file name.
+.It Fl C | Fl -demangle
+Demangle C++ names.
+.It Fl H | Fl -help
+Print a help message.
+.It Fl V | Fl -version
+Print a version identifier and exit.
+.El
+.Sh OUTPUT FORMAT
+If the
+.Fl f
+option was not specified,
+.Nm
+will print the file name and line number for each address specified
+on a separate line.
+.Pp
+If the
+.Fl f
+option was specified,
+.Nm
+will print a line containing the name of the function corresponding
+to program address
+.Ar hexaddress ,
+followed by a line with the file name and line number.
+.Pp
+If the
+.Fl p
+option was specified,
+.Nm
+will print line number information and function name on one line in
+human readable manner. If the
+.Fl i
+option was also specified,
+.Nm
+will print the caller function information prefixed with
+.Dq (inlined by) .
+.Pp
+The
+.Nm
+utility prints the file name and line number using the format
+.Dq FILENAME:LINENUMBER .
+.Pp
+If a file or function name could not be determined,
+.Nm
+will print a question mark in their place.
+If the line number could not be determined,
+.Nm
+will print a zero in its place.
+.Sh EXAMPLES
+To map address 080483c4 in the default executable
+.Pa a.out
+to a source file name and line number use:
+.D1 "% addr2line 080483c4"
+.Pp
+To map address 080483c4 in executable
+.Pa helloworld ,
+use:
+.D1 "% addr2line -e helloworld 080483c4"
+.Pp
+To have
+.Nm
+act as a filter reading addresses from its standard input use:
+.D1 "% addr2line"
+.Pp
+To print the function name corresponding to an address in addition to
+its source file and line number use:
+.D1 "% addr2line -f 080483c4"
+.Sh EXIT STATUS
+.Ex -std
+.Sh SEE ALSO
+.Xr nm 1 ,
+.Xr elfdump 1 ,
+.Xr elfcopy 1 ,
+.Xr strtoull 3
+.Sh AUTHORS
+The
+.Nm
+utility was written by
+.An Kai Wang Aq Mt kaiwang27@users.sourceforge.net .
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/addr2line/addr2line.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,734 @@
+/*-
+ * Copyright (c) 2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <dwarf.h>
+#include <err.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <getopt.h>
+#include <libdwarf.h>
+#include <libelftc.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "uthash.h"
+#include "_elftc.h"
+
+ELFTC_VCSID("$Id: addr2line.c 3499 2016-11-25 16:06:29Z emaste $");
+
+struct Func {
+	char *name;
+	Dwarf_Unsigned lopc;
+	Dwarf_Unsigned hipc;
+	Dwarf_Unsigned call_file;
+	Dwarf_Unsigned call_line;
+	Dwarf_Ranges *ranges;
+	Dwarf_Signed ranges_cnt;
+	struct Func *inlined_caller;
+	STAILQ_ENTRY(Func) next;
+};
+
+struct CU {
+	Dwarf_Off off;
+	Dwarf_Unsigned lopc;
+	Dwarf_Unsigned hipc;
+	char **srcfiles;
+	Dwarf_Signed nsrcfiles;
+	STAILQ_HEAD(, Func) funclist;
+	UT_hash_handle hh;
+};
+
+static struct option longopts[] = {
+	{"addresses", no_argument, NULL, 'a'},
+	{"target" , required_argument, NULL, 'b'},
+	{"demangle", no_argument, NULL, 'C'},
+	{"exe", required_argument, NULL, 'e'},
+	{"functions", no_argument, NULL, 'f'},
+	{"inlines", no_argument, NULL, 'i'},
+	{"section", required_argument, NULL, 'j'},
+	{"pretty-print", no_argument, NULL, 'p'},
+	{"basename", no_argument, NULL, 's'},
+	{"help", no_argument, NULL, 'H'},
+	{"version", no_argument, NULL, 'V'},
+	{NULL, 0, NULL, 0}
+};
+static int demangle, func, base, inlines, print_addr, pretty_print;
+static char unknown[] = { '?', '?', '\0' };
+static Dwarf_Addr section_base;
+static struct CU *culist;
+
+#define	USAGE_MESSAGE	"\
+Usage: %s [options] hexaddress...\n\
+  Map program addresses to source file names and line numbers.\n\n\
+  Options:\n\
+  -a      | --addresses       Display address prior to line number info.\n\
+  -b TGT  | --target=TGT      (Accepted but ignored).\n\
+  -e EXE  | --exe=EXE         Use program \"EXE\" to translate addresses.\n\
+  -f      | --functions       Display function names.\n\
+  -i      | --inlines         Display caller info for inlined functions.\n\
+  -j NAME | --section=NAME    Values are offsets into section \"NAME\".\n\
+  -p      | --pretty-print    Display line number info and function name\n\
+                              in human readable manner.\n\
+  -s      | --basename        Only show the base name for each file name.\n\
+  -C      | --demangle        Demangle C++ names.\n\
+  -H      | --help            Print a help message.\n\
+  -V      | --version         Print a version identifier and exit.\n"
+
+static void
+usage(void)
+{
+	(void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
+	exit(1);
+}
+
+static void
+version(void)
+{
+
+	fprintf(stderr, "%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version());
+	exit(0);
+}
+
+/*
+ * Handle DWARF 4 'offset from' DW_AT_high_pc.  Although we don't
+ * fully support DWARF 4, some compilers (like FreeBSD Clang 3.5.1)
+ * generate DW_AT_high_pc as an offset from DW_AT_low_pc.
+ *
+ * "If the value of the DW_AT_high_pc is of class address, it is the
+ * relocated address of the first location past the last instruction
+ * associated with the entity; if it is of class constant, the value
+ * is an unsigned integer offset which when added to the low PC gives
+ * the address of the first location past the last instruction
+ * associated with the entity."
+ *
+ * DWARF4 spec, section 2.17.2.
+ */
+static int
+handle_high_pc(Dwarf_Die die, Dwarf_Unsigned lopc, Dwarf_Unsigned *hipc)
+{
+	Dwarf_Error de;
+	Dwarf_Half form;
+	Dwarf_Attribute at;
+	int ret;
+
+	ret = dwarf_attr(die, DW_AT_high_pc, &at, &de);
+	if (ret == DW_DLV_ERROR) {
+		warnx("dwarf_attr failed: %s", dwarf_errmsg(de));
+		return (ret);
+	}
+	ret = dwarf_whatform(at, &form, &de);
+	if (ret == DW_DLV_ERROR) {
+		warnx("dwarf_whatform failed: %s", dwarf_errmsg(de));
+		return (ret);
+	}
+	if (dwarf_get_form_class(2, 0, 0, form) == DW_FORM_CLASS_CONSTANT)
+		*hipc += lopc;
+
+	return (DW_DLV_OK);
+}
+
+static struct Func *
+search_func(struct CU *cu, Dwarf_Unsigned addr)
+{
+	struct Func *f, *f0;
+	Dwarf_Unsigned lopc, hipc, addr_base;
+	int i;
+
+	f0 = NULL;
+
+	STAILQ_FOREACH(f, &cu->funclist, next) {
+		if (f->ranges != NULL) {
+			addr_base = 0;
+			for (i = 0; i < f->ranges_cnt; i++) {
+				if (f->ranges[i].dwr_type == DW_RANGES_END)
+					break;
+				if (f->ranges[i].dwr_type ==
+				    DW_RANGES_ADDRESS_SELECTION) {
+					addr_base = f->ranges[i].dwr_addr2;
+					continue;
+				}
+
+				/* DW_RANGES_ENTRY */
+				lopc = f->ranges[i].dwr_addr1 + addr_base;
+				hipc = f->ranges[i].dwr_addr2 + addr_base;
+				if (addr >= lopc && addr < hipc) {
+					if (f0 == NULL ||
+					    (lopc >= f0->lopc &&
+					    hipc <= f0->hipc)) {
+						f0 = f;
+						f0->lopc = lopc;
+						f0->hipc = hipc;
+						break;
+					}
+				}
+			}
+		} else if (addr >= f->lopc && addr < f->hipc) {
+			if (f0 == NULL ||
+			    (f->lopc >= f0->lopc && f->hipc <= f0->hipc))
+				f0 = f;
+		}
+	}
+
+	return (f0);
+}
+
+static void
+collect_func(Dwarf_Debug dbg, Dwarf_Die die, struct Func *parent, struct CU *cu)
+{
+	Dwarf_Die ret_die, abst_die, spec_die;
+	Dwarf_Error de;
+	Dwarf_Half tag;
+	Dwarf_Unsigned lopc, hipc, ranges_off;
+	Dwarf_Signed ranges_cnt;
+	Dwarf_Off ref;
+	Dwarf_Attribute abst_at, spec_at;
+	Dwarf_Ranges *ranges;
+	const char *funcname;
+	struct Func *f;
+	int found_ranges, ret;
+
+	f = NULL;
+	abst_die = spec_die = NULL;
+
+	if (dwarf_tag(die, &tag, &de)) {
+		warnx("dwarf_tag: %s", dwarf_errmsg(de));
+		goto cont_search;
+	}
+	if (tag == DW_TAG_subprogram || tag == DW_TAG_entry_point ||
+	    tag == DW_TAG_inlined_subroutine) {
+		/*
+		 * Function address range can be specified by either
+		 * a DW_AT_ranges attribute which points to a range list or
+		 * by a pair of DW_AT_low_pc and DW_AT_high_pc attributes.
+		 */
+		ranges = NULL;
+		ranges_cnt = 0;
+		found_ranges = 0;
+		if (dwarf_attrval_unsigned(die, DW_AT_ranges, &ranges_off,
+		    &de) == DW_DLV_OK &&
+		    dwarf_get_ranges(dbg, (Dwarf_Off) ranges_off, &ranges,
+		    &ranges_cnt, NULL, &de) == DW_DLV_OK) {
+			if (ranges != NULL && ranges_cnt > 0) {
+				found_ranges = 1;
+				goto get_func_name;
+			}
+		}
+
+		/*
+		 * Search for DW_AT_low_pc/DW_AT_high_pc if ranges pointer
+		 * not found.
+		 */
+		if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) ||
+		    dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, &de))
+			goto cont_search;
+		if (handle_high_pc(die, lopc, &hipc) != DW_DLV_OK)
+			goto cont_search;
+
+	get_func_name:
+		/*
+		 * Most common case the function name is stored in DW_AT_name
+		 * attribute.
+		 */
+		if (dwarf_attrval_string(die, DW_AT_name, &funcname, &de) ==
+		    DW_DLV_OK)
+			goto add_func;
+
+		/*
+		 * For inlined function, the actual name is probably in the DIE
+		 * referenced by DW_AT_abstract_origin. (if present)
+		 */
+		if (dwarf_attr(die, DW_AT_abstract_origin, &abst_at, &de) ==
+		    DW_DLV_OK &&
+		    dwarf_global_formref(abst_at, &ref, &de) == DW_DLV_OK &&
+		    dwarf_offdie(dbg, ref, &abst_die, &de) == DW_DLV_OK &&
+		    dwarf_attrval_string(abst_die, DW_AT_name, &funcname,
+		    &de) == DW_DLV_OK)
+			goto add_func;
+
+		/*
+		 * If DW_AT_name is not present, but DW_AT_specification is
+		 * present, then probably the actual name is in the DIE
+		 * referenced by DW_AT_specification.
+		 */
+		if (dwarf_attr(die, DW_AT_specification, &spec_at, &de) ==
+		    DW_DLV_OK &&
+		    dwarf_global_formref(spec_at, &ref, &de) == DW_DLV_OK &&
+		    dwarf_offdie(dbg, ref, &spec_die, &de) == DW_DLV_OK &&
+		    dwarf_attrval_string(spec_die, DW_AT_name, &funcname,
+		    &de) == DW_DLV_OK)
+			goto add_func;
+
+		/* Skip if no name associated with this DIE. */
+		goto cont_search;
+
+	add_func:
+		if ((f = calloc(1, sizeof(*f))) == NULL)
+			err(EXIT_FAILURE, "calloc");
+		if ((f->name = strdup(funcname)) == NULL)
+			err(EXIT_FAILURE, "strdup");
+		if (found_ranges) {
+			f->ranges = ranges;
+			f->ranges_cnt = ranges_cnt;
+		} else {
+			f->lopc = lopc;
+			f->hipc = hipc;
+		}
+		if (tag == DW_TAG_inlined_subroutine) {
+			f->inlined_caller = parent;
+			dwarf_attrval_unsigned(die, DW_AT_call_file,
+			    &f->call_file, &de);
+			dwarf_attrval_unsigned(die, DW_AT_call_line,
+			    &f->call_line, &de);
+		}
+		STAILQ_INSERT_TAIL(&cu->funclist, f, next);
+	}
+
+cont_search:
+
+	/* Search children. */
+	ret = dwarf_child(die, &ret_die, &de);
+	if (ret == DW_DLV_ERROR)
+		warnx("dwarf_child: %s", dwarf_errmsg(de));
+	else if (ret == DW_DLV_OK) {
+		if (f != NULL)
+			collect_func(dbg, ret_die, f, cu);
+		else
+			collect_func(dbg, ret_die, parent, cu);
+	}
+
+	/* Search sibling. */
+	ret = dwarf_siblingof(dbg, die, &ret_die, &de);
+	if (ret == DW_DLV_ERROR)
+		warnx("dwarf_siblingof: %s", dwarf_errmsg(de));
+	else if (ret == DW_DLV_OK)
+		collect_func(dbg, ret_die, parent, cu);
+
+	/* Cleanup */
+	dwarf_dealloc(dbg, die, DW_DLA_DIE);
+
+	if (abst_die != NULL)
+		dwarf_dealloc(dbg, abst_die, DW_DLA_DIE);
+
+	if (spec_die != NULL)
+		dwarf_dealloc(dbg, spec_die, DW_DLA_DIE);
+}
+
+static void
+print_inlines(struct CU *cu, struct Func *f, Dwarf_Unsigned call_file,
+    Dwarf_Unsigned call_line)
+{
+	char demangled[1024];
+	char *file;
+
+	if (call_file > 0 && (Dwarf_Signed) call_file <= cu->nsrcfiles)
+		file = cu->srcfiles[call_file - 1];
+	else
+		file = unknown;
+
+	if (pretty_print)
+		printf(" (inlined by) ");
+
+	if (func) {
+		if (demangle && !elftc_demangle(f->name, demangled,
+		    sizeof(demangled), 0)) {
+			if (pretty_print)
+				printf("%s at ", demangled);
+			else
+				printf("%s\n", demangled);
+		} else {
+			if (pretty_print)
+				printf("%s at ", f->name);
+			else
+				printf("%s\n", f->name);
+		}
+	}
+	(void) printf("%s:%ju\n", base ? basename(file) : file,
+	    (uintmax_t) call_line);
+
+	if (f->inlined_caller != NULL)
+		print_inlines(cu, f->inlined_caller, f->call_file,
+		    f->call_line);
+}
+
+static void
+translate(Dwarf_Debug dbg, Elf *e, const char* addrstr)
+{
+	Dwarf_Die die, ret_die;
+	Dwarf_Line *lbuf;
+	Dwarf_Error de;
+	Dwarf_Half tag;
+	Dwarf_Unsigned lopc, hipc, addr, lineno, plineno;
+	Dwarf_Signed lcount;
+	Dwarf_Addr lineaddr, plineaddr;
+	Dwarf_Off off;
+	struct CU *cu;
+	struct Func *f;
+	const char *funcname;
+	char *file, *file0, *pfile;
+	char demangled[1024];
+	int ec, i, ret;
+
+	addr = strtoull(addrstr, NULL, 16);
+	addr += section_base;
+	lineno = 0;
+	file = unknown;
+	cu = NULL;
+	die = NULL;
+
+	while ((ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL,
+	    &de)) ==  DW_DLV_OK) {
+		die = NULL;
+		while (dwarf_siblingof(dbg, die, &ret_die, &de) == DW_DLV_OK) {
+			if (die != NULL)
+				dwarf_dealloc(dbg, die, DW_DLA_DIE);
+			die = ret_die;
+			if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
+				warnx("dwarf_tag failed: %s",
+				    dwarf_errmsg(de));
+				goto next_cu;
+			}
+
+			/* XXX: What about DW_TAG_partial_unit? */
+			if (tag == DW_TAG_compile_unit)
+				break;
+		}
+		if (ret_die == NULL) {
+			warnx("could not find DW_TAG_compile_unit die");
+			goto next_cu;
+		}
+		if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) ==
+		    DW_DLV_OK) {
+			if (dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc,
+			   &de) == DW_DLV_OK) {
+				/*
+				 * Check if the address falls into the PC
+				 * range of this CU.
+				 */
+				if (handle_high_pc(die, lopc, &hipc) !=
+				    DW_DLV_OK)
+					goto out;
+			} else {
+				/* Assume ~0ULL if DW_AT_high_pc not present */
+				hipc = ~0ULL;
+			}
+
+			/*
+			 * Record the CU in the hash table for faster lookup
+			 * later.
+			 */
+			if (dwarf_dieoffset(die, &off, &de) != DW_DLV_OK) {
+				warnx("dwarf_dieoffset failed: %s",
+				    dwarf_errmsg(de));
+				goto out;
+			}
+			HASH_FIND(hh, culist, &off, sizeof(off), cu);
+			if (cu == NULL) {
+				if ((cu = calloc(1, sizeof(*cu))) == NULL)
+					err(EXIT_FAILURE, "calloc");
+				cu->off = off;
+				cu->lopc = lopc;
+				cu->hipc = hipc;
+				STAILQ_INIT(&cu->funclist);
+				HASH_ADD(hh, culist, off, sizeof(off), cu);
+			}
+
+			if (addr >= lopc && addr < hipc)
+				break;
+		}
+
+	next_cu:
+		if (die != NULL) {
+			dwarf_dealloc(dbg, die, DW_DLA_DIE);
+			die = NULL;
+		}
+	}
+
+	if (ret != DW_DLV_OK || die == NULL)
+		goto out;
+
+	switch (dwarf_srclines(die, &lbuf, &lcount, &de)) {
+	case DW_DLV_OK:
+		break;
+	case DW_DLV_NO_ENTRY:
+		/* If a CU lacks debug info, just skip it. */
+		goto out;
+	default:
+		warnx("dwarf_srclines: %s", dwarf_errmsg(de));
+		goto out;
+	}
+
+	plineaddr = ~0ULL;
+	plineno = 0;
+	pfile = unknown;
+	for (i = 0; i < lcount; i++) {
+		if (dwarf_lineaddr(lbuf[i], &lineaddr, &de)) {
+			warnx("dwarf_lineaddr: %s", dwarf_errmsg(de));
+			goto out;
+		}
+		if (dwarf_lineno(lbuf[i], &lineno, &de)) {
+			warnx("dwarf_lineno: %s", dwarf_errmsg(de));
+			goto out;
+		}
+		if (dwarf_linesrc(lbuf[i], &file0, &de)) {
+			warnx("dwarf_linesrc: %s", dwarf_errmsg(de));
+		} else
+			file = file0;
+		if (addr == lineaddr)
+			goto out;
+		else if (addr < lineaddr && addr > plineaddr) {
+			lineno = plineno;
+			file = pfile;
+			goto out;
+		}
+		plineaddr = lineaddr;
+		plineno = lineno;
+		pfile = file;
+	}
+
+out:
+	f = NULL;
+	funcname = NULL;
+	if (ret == DW_DLV_OK && (func || inlines) && cu != NULL) {
+		if (cu->srcfiles == NULL)
+			if (dwarf_srcfiles(die, &cu->srcfiles, &cu->nsrcfiles,
+			    &de))
+				warnx("dwarf_srcfiles: %s", dwarf_errmsg(de));
+		if (STAILQ_EMPTY(&cu->funclist)) {
+			collect_func(dbg, die, NULL, cu);
+			die = NULL;
+		}
+		f = search_func(cu, addr);
+		if (f != NULL)
+			funcname = f->name;
+	}
+
+	if (print_addr) {
+		if ((ec = gelf_getclass(e)) == ELFCLASSNONE) {
+			warnx("gelf_getclass failed: %s", elf_errmsg(-1));
+			ec = ELFCLASS64;
+		}
+		if (ec == ELFCLASS32) {
+			if (pretty_print)
+				printf("0x%08jx: ", (uintmax_t) addr);
+			else
+				printf("0x%08jx\n", (uintmax_t) addr);
+		} else {
+			if (pretty_print)
+				printf("0x%016jx: ", (uintmax_t) addr);
+			else
+				printf("0x%016jx\n", (uintmax_t) addr);
+		}
+	}
+
+	if (func) {
+		if (funcname == NULL)
+			funcname = unknown;
+		if (demangle && !elftc_demangle(funcname, demangled,
+		    sizeof(demangled), 0)) {
+			if (pretty_print)
+				printf("%s at ", demangled);
+			else
+				printf("%s\n", demangled);
+		} else {
+			if (pretty_print)
+				printf("%s at ", funcname);
+			else
+				printf("%s\n", funcname);
+		}
+	}
+
+	(void) printf("%s:%ju\n", base ? basename(file) : file,
+	    (uintmax_t) lineno);
+
+	if (ret == DW_DLV_OK && inlines && cu != NULL &&
+	    cu->srcfiles != NULL && f != NULL && f->inlined_caller != NULL)
+		print_inlines(cu, f->inlined_caller, f->call_file,
+		    f->call_line);
+
+	if (die != NULL)
+		dwarf_dealloc(dbg, die, DW_DLA_DIE);
+
+	/*
+	 * Reset internal CU pointer, so we will start from the first CU
+	 * next round.
+	 */
+	while (ret != DW_DLV_NO_ENTRY) {
+		if (ret == DW_DLV_ERROR)
+			errx(EXIT_FAILURE, "dwarf_next_cu_header: %s",
+			    dwarf_errmsg(de));
+		ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL,
+		    &de);
+	}
+}
+
+static void
+find_section_base(const char *exe, Elf *e, const char *section)
+{
+	Dwarf_Addr off;
+	Elf_Scn *scn;
+	GElf_Ehdr eh;
+	GElf_Shdr sh;
+	size_t shstrndx;
+	int elferr;
+	const char *name;
+
+	if (gelf_getehdr(e, &eh) != &eh) {
+		warnx("gelf_getehdr failed: %s", elf_errmsg(-1));
+		return;
+	}
+
+	if (!elf_getshstrndx(e, &shstrndx)) {
+		warnx("elf_getshstrndx failed: %s", elf_errmsg(-1));
+		return;
+	}
+
+	(void) elf_errno();
+	off = 0;
+	scn = NULL;
+	while ((scn = elf_nextscn(e, scn)) != NULL) {
+		if (gelf_getshdr(scn, &sh) == NULL) {
+			warnx("gelf_getshdr failed: %s", elf_errmsg(-1));
+			continue;
+		}
+		if ((name = elf_strptr(e, shstrndx, sh.sh_name)) == NULL)
+			goto next;
+		if (!strcmp(section, name)) {
+			if (eh.e_type == ET_EXEC || eh.e_type == ET_DYN) {
+				/*
+				 * For executables, section base is the virtual
+				 * address of the specified section.
+				 */
+				section_base = sh.sh_addr;
+			} else if (eh.e_type == ET_REL) {
+				/*
+				 * For relocatables, section base is the
+				 * relative offset of the specified section
+				 * to the start of the first section.
+				 */
+				section_base = off;
+			} else
+				warnx("unknown e_type %u", eh.e_type);
+			return;
+		}
+	next:
+		off += sh.sh_size;
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		warnx("elf_nextscn failed: %s", elf_errmsg(elferr));
+
+	errx(EXIT_FAILURE, "%s: cannot find section %s", exe, section);
+}
+
+int
+main(int argc, char **argv)
+{
+	Elf *e;
+	Dwarf_Debug dbg;
+	Dwarf_Error de;
+	const char *exe, *section;
+	char line[1024];
+	int fd, i, opt;
+
+	exe = NULL;
+	section = NULL;
+	while ((opt = getopt_long(argc, argv, "ab:Ce:fij:psHV", longopts,
+	    NULL)) != -1) {
+		switch (opt) {
+		case 'a':
+			print_addr = 1;
+			break;
+		case 'b':
+			/* ignored */
+			break;
+		case 'C':
+			demangle = 1;
+			break;
+		case 'e':
+			exe = optarg;
+			break;
+		case 'f':
+			func = 1;
+			break;
+		case 'i':
+			inlines = 1;
+			break;
+		case 'j':
+			section = optarg;
+			break;
+		case 'p':
+			pretty_print = 1;
+			break;
+		case 's':
+			base = 1;
+			break;
+		case 'H':
+			usage();
+		case 'V':
+			version();
+		default:
+			usage();
+		}
+	}
+
+	argv += optind;
+	argc -= optind;
+
+	if (exe == NULL)
+		exe = "a.out";
+
+	if ((fd = open(exe, O_RDONLY)) < 0)
+		err(EXIT_FAILURE, "%s", exe);
+
+	if (dwarf_init(fd, DW_DLC_READ, NULL, NULL, &dbg, &de))
+		errx(EXIT_FAILURE, "dwarf_init: %s", dwarf_errmsg(de));
+
+	if (dwarf_get_elf(dbg, &e, &de) != DW_DLV_OK)
+		errx(EXIT_FAILURE, "dwarf_get_elf: %s", dwarf_errmsg(de));
+
+	if (section)
+		find_section_base(exe, e, section);
+	else
+		section_base = 0;
+
+	if (argc > 0)
+		for (i = 0; i < argc; i++)
+			translate(dbg, e, argv[i]);
+	else {
+		setvbuf(stdout, NULL, _IOLBF, 0);
+		while (fgets(line, sizeof(line), stdin) != NULL)
+			translate(dbg, e, line);
+	}
+
+	dwarf_finish(dbg, &de);
+
+	(void) elf_end(e);
+
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/addr2line/os.NetBSD.mk	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,2 @@
+# TODO(#511): Revert after the source tree is -Wconversion clean.
+WARNS=5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/ar/Makefile	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,37 @@
+# $Id: Makefile 3608 2018-04-14 21:23:04Z jkoshy $
+
+TOP=	..
+
+PROG=	ar
+SRCS=	ar.c read.c util.c write.c
+LSRC=	acplex.l
+YSRC=	acpyacc.y
+
+WARNS?=	5
+
+DPADD=	${LIBARCHIVE} ${LIBELFTC} ${LIBELF} ${LIBZ}
+LDADD=	-larchive -lelftc -lelf -lz
+
+CFLAGS+=-I. -I${.CURDIR}
+
+LINKS=	${BINDIR}/ar ${BINDIR}/ranlib
+
+EXTRA_TARGETS=	ranlib
+
+CLEANFILES+= 	${EXTRA_TARGETS}
+
+MAN=	ar.1 ranlib.1 ar.5
+
+all:	${EXTRA_TARGETS}
+
+${EXTRA_TARGETS}:	${PROG}
+	ln -s ${PROG} ${.TARGET}
+
+.include "${TOP}/mk/elftoolchain.prog.mk"
+
+.if ${OS_HOST} == "OpenBSD"
+CFLAGS+=	-I/usr/local/include
+LDFLAGS+=	-L/usr/local/lib
+.elif ${OS_HOST} == "DragonFly"
+LDADD+=	-lbz2
+.endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/ar/acplex.l	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,83 @@
+%{
+/*-
+ * Copyright (c) 2008 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "_elftc.h"
+
+ELFTC_VCSID("$Id: acplex.l 3174 2015-03-27 17:13:41Z emaste $");
+
+#include "acpyacc.h"
+
+#define YY_NO_UNPUT
+#if !defined(ELFTC_BROKEN_YY_NO_INPUT)
+#define YY_NO_INPUT
+#endif
+
+int lineno = 1;
+
+int	yylex(void);
+
+%}
+
+%option nounput
+%option noyywrap
+
+%%
+
+ADDLIB|addlib		{ return (ADDLIB); }
+ADDMOD|addmod		{ return (ADDMOD); }
+CLEAR|clear		{ return (CLEAR); }
+CREATE|create		{ return (CREATE); }
+DELETE|delete		{ return (DELETE); }
+DIRECTORY|directory	{ return (DIRECTORY); }
+END|end			{ return (END); }
+EXTRACT|extract		{ return (EXTRACT); }
+LIST|list		{ return (LIST); }
+OPEN|open		{ return (OPEN); }
+REPLACE|replace		{ return (REPLACE); }
+VERBOSE|verbose		{ return (VERBOSE); }
+SAVE|save		{ return (SAVE); }
+"("			{ return (LP); }
+")"			{ return (RP); }
+","			{ return (COMMA); }
+
+[-_A-Za-z0-9/:$.\\]+	{
+	yylval.str = strdup(yytext);
+	if (yylval.str == NULL)
+		err(EXIT_FAILURE, "strdup failed");
+	return (FNAME);
+}
+
+[ \t]			/* whitespace */
+"*".*			/* comment */
+";".*			/* comment */
+"+\n"			{ lineno++; /* '+' is line continuation char */ }
+"\n"			{ lineno++; return (EOL); }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/ar/acpyacc.y	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,658 @@
+%{
+/*-
+ * Copyright (c) 2008 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/mman.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <archive.h>
+#include <archive_entry.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "libelftc.h"
+
+#include "ar.h"
+
+ELFTC_VCSID("$Id");
+
+
+#define TEMPLATE "arscp.XXXXXXXX"
+
+struct list {
+	char		*str;
+	struct list	*next;
+};
+
+
+extern int	yylex(void);
+extern int	yyparse(void);
+
+static void	yyerror(const char *);
+static void	arscp_addlib(char *archive, struct list *list);
+static void	arscp_addmod(struct list *list);
+static void	arscp_clear(void);
+static void	arscp_create(char *in, char *out);
+static void	arscp_delete(struct list *list);
+static void	arscp_dir(char *archive, struct list *list, char *rlt);
+static void	arscp_end(int eval);
+static void	arscp_extract(struct list *list);
+static void	arscp_free_argv(void);
+static void	arscp_free_mlist(struct list *list);
+static void	arscp_list(void);
+static struct list *arscp_mlist(struct list *list, char *str);
+static void	arscp_mlist2argv(struct list *list);
+static int	arscp_mlist_len(struct list *list);
+static void	arscp_open(char *fname);
+static void	arscp_prompt(void);
+static void	arscp_replace(struct list *list);
+static void	arscp_save(void);
+static int	arscp_target_exist(void);
+
+extern int		 lineno;
+
+static struct bsdar	*bsdar;
+static char		*target;
+static char		*tmpac;
+static int		 interactive;
+static int		 verbose;
+
+%}
+
+%token ADDLIB
+%token ADDMOD
+%token CLEAR
+%token CREATE
+%token DELETE
+%token DIRECTORY
+%token END
+%token EXTRACT
+%token LIST
+%token OPEN
+%token REPLACE
+%token VERBOSE
+%token SAVE
+%token LP
+%token RP
+%token COMMA
+%token EOL
+%token <str> FNAME
+%type <list> mod_list
+
+%union {
+	char		*str;
+	struct list	*list;
+}
+
+%%
+
+begin
+	: { arscp_prompt(); } ar_script
+	;
+
+ar_script
+	: cmd_list
+	|
+	;
+
+mod_list
+	: FNAME { $$ = arscp_mlist(NULL, $1); }
+	| mod_list separator FNAME { $$ = arscp_mlist($1, $3); }
+	;
+
+separator
+	: COMMA
+	|
+	;
+
+cmd_list
+	: rawcmd
+	| cmd_list rawcmd
+	;
+
+rawcmd
+	: cmd EOL { arscp_prompt(); }
+	;
+
+cmd
+	: addlib_cmd
+	| addmod_cmd
+	| clear_cmd
+	| create_cmd
+	| delete_cmd
+	| directory_cmd
+	| end_cmd
+	| extract_cmd
+	| list_cmd
+	| open_cmd
+	| replace_cmd
+	| verbose_cmd
+	| save_cmd
+	| invalid_cmd
+	| empty_cmd
+	| error
+	;
+
+addlib_cmd
+	: ADDLIB FNAME LP mod_list RP { arscp_addlib($2, $4); }
+	| ADDLIB FNAME { arscp_addlib($2, NULL); }
+	;
+
+addmod_cmd
+	: ADDMOD mod_list { arscp_addmod($2); }
+	;
+
+clear_cmd
+	: CLEAR { arscp_clear(); }
+	;
+
+create_cmd
+	: CREATE FNAME { arscp_create(NULL, $2); }
+	;
+
+delete_cmd
+	: DELETE mod_list { arscp_delete($2); }
+	;
+
+directory_cmd
+	: DIRECTORY FNAME { arscp_dir($2, NULL, NULL); }
+	| DIRECTORY FNAME LP mod_list RP { arscp_dir($2, $4, NULL); }
+	| DIRECTORY FNAME LP mod_list RP FNAME { arscp_dir($2, $4, $6); }
+	;
+
+end_cmd
+	: END { arscp_end(EXIT_SUCCESS); }
+	;
+
+extract_cmd
+	: EXTRACT mod_list { arscp_extract($2); }
+	;
+
+list_cmd
+	: LIST { arscp_list(); }
+	;
+
+open_cmd
+	: OPEN FNAME { arscp_open($2); }
+	;
+
+replace_cmd
+	: REPLACE mod_list { arscp_replace($2); }
+	;
+
+save_cmd
+	: SAVE { arscp_save(); }
+	;
+
+verbose_cmd
+	: VERBOSE { verbose = !verbose; }
+	;
+
+empty_cmd
+	:
+	;
+
+invalid_cmd
+	: FNAME { yyerror(NULL); }
+	;
+
+%%
+
+/* ARGSUSED */
+static void
+yyerror(const char *s)
+{
+
+	(void) s;
+	printf("Syntax error in archive script, line %d\n", lineno);
+}
+
+/*
+ * The arscp_open() function will first open an archive and check its
+ * validity. If the archive format is valid, it will call
+ * arscp_create() to create a temporary copy of the archive.
+ */
+static void
+arscp_open(char *fname)
+{
+	struct archive		*a;
+	struct archive_entry	*entry;
+	int			 r;
+
+	if ((a = archive_read_new()) == NULL)
+		bsdar_errc(bsdar, 0, "archive_read_new failed");
+	archive_read_support_format_ar(a);
+	AC(archive_read_open_filename(a, fname, DEF_BLKSZ));
+	if ((r = archive_read_next_header(a, &entry)))
+		bsdar_warnc(bsdar, 0, "%s", archive_error_string(a));
+	AC(archive_read_close(a));
+	ACV(archive_read_free(a));
+	if (r != ARCHIVE_OK)
+		return;
+	arscp_create(fname, fname);
+}
+
+/*
+ * Create an archive.
+ *
+ * If the parameter 'in' is NULL (the 'CREATE' command), a new empty
+ * archive will be created.  If the parameter 'in' is not NULL (the
+ * 'OPEN' command), the resulting archive will be a modified version
+ * of the existing archive.
+ */
+static void
+arscp_create(char *in, char *out)
+{
+	struct archive		*a;
+	int			 ifd, ofd;
+
+	/* Delete the previously created temporary archive, if any. */
+	if (tmpac) {
+		if (unlink(tmpac) < 0)
+			bsdar_errc(bsdar, errno, "unlink failed");
+		free(tmpac);
+	}
+
+	tmpac = strdup(TEMPLATE);
+	if (tmpac == NULL)
+		bsdar_errc(bsdar, errno, "strdup failed");
+	if ((ofd = mkstemp(tmpac)) < 0)
+		bsdar_errc(bsdar, errno, "mkstemp failed");
+
+	if (in) {
+		/*
+		 * The 'OPEN' command creates a temporary copy of the
+		 * input archive.
+		 */
+		if ((ifd = open(in, O_RDONLY)) < 0 ||
+		    elftc_copyfile(ifd, ofd) < 0) {
+			bsdar_warnc(bsdar, errno, "'OPEN' failed");
+			(void) close(ofd);
+			if (ifd != -1)
+				(void) close(ifd);
+			return;
+		}
+		(void) close(ifd);
+		(void) close(ofd);
+	} else {
+		/*
+		 * The 'CREATE' command creates an "empty" archive (an
+		 * archive consisting only of the archive header).
+		 */
+		if ((a = archive_write_new()) == NULL)
+			bsdar_errc(bsdar, 0, "archive_write_new failed");
+		archive_write_set_format_ar_svr4(a);
+		AC(archive_write_open_fd(a, ofd));
+		AC(archive_write_close(a));
+		ACV(archive_write_free(a));
+	}
+
+	/* Override the previous target, if any. */
+	if (target)
+		free(target);
+
+	target = out;
+	bsdar->filename = tmpac;
+}
+
+/*
+ * Add all modules of an archive to the current archive.  If the
+ * parameter 'list' is not NULL, only those modules specified by
+ * 'list' will be added.
+ */
+static void
+arscp_addlib(char *archive, struct list *list)
+{
+
+	if (!arscp_target_exist())
+		return;
+	arscp_mlist2argv(list);
+	bsdar->addlib = archive;
+	ar_write_archive(bsdar, 'A');
+	arscp_free_argv();
+	arscp_free_mlist(list);
+}
+
+/*
+ * Add modules to the current archive.
+ */
+static void
+arscp_addmod(struct list *list)
+{
+
+	if (!arscp_target_exist())
+		return;
+	arscp_mlist2argv(list);
+	ar_write_archive(bsdar, 'q');
+	arscp_free_argv();
+	arscp_free_mlist(list);
+}
+
+/*
+ * Delete modules from the current archive.
+ */
+static void
+arscp_delete(struct list *list)
+{
+
+	if (!arscp_target_exist())
+		return;
+	arscp_mlist2argv(list);
+	ar_write_archive(bsdar, 'd');
+	arscp_free_argv();
+	arscp_free_mlist(list);
+}
+
+/*
+ * Extract modules from the current archive.
+ */
+static void
+arscp_extract(struct list *list)
+{
+
+	if (!arscp_target_exist())
+		return;
+	arscp_mlist2argv(list);
+	ar_read_archive(bsdar, 'x');
+	arscp_free_argv();
+	arscp_free_mlist(list);
+}
+
+/*
+ * List the contents of an archive (simple mode).
+ */
+static void
+arscp_list(void)
+{
+
+	if (!arscp_target_exist())
+		return;
+	bsdar->argc = 0;
+	bsdar->argv = NULL;
+	/* Always verbose. */
+	bsdar->options |= AR_V;
+	ar_read_archive(bsdar, 't');
+	bsdar->options &= ~AR_V;
+}
+
+/*
+ * List the contents of an archive (advanced mode).
+ */
+static void
+arscp_dir(char *archive, struct list *list, char *rlt)
+{
+	FILE	*out;
+
+	/* If rlt != NULL, redirect the output to it. */
+	out = NULL;
+	if (rlt) {
+		out = bsdar->output;
+		if ((bsdar->output = fopen(rlt, "w")) == NULL)
+			bsdar_errc(bsdar, errno, "fopen %s failed", rlt);
+	}
+
+	bsdar->filename = archive;
+	if (list)
+		arscp_mlist2argv(list);
+	else {
+		bsdar->argc = 0;
+		bsdar->argv = NULL;
+	}
+	if (verbose)
+		bsdar->options |= AR_V;
+	ar_read_archive(bsdar, 't');
+	bsdar->options &= ~AR_V;
+
+	if (rlt) {
+		if (fclose(bsdar->output) == EOF)
+			bsdar_errc(bsdar, errno, "fclose %s failed", rlt);
+		bsdar->output = out;
+		free(rlt);
+	}
+	free(archive);
+	bsdar->filename = tmpac;
+	arscp_free_argv();
+	arscp_free_mlist(list);
+}
+
+
+/*
+ * Replace modules in the current archive.
+ */
+static void
+arscp_replace(struct list *list)
+{
+
+	if (!arscp_target_exist())
+		return;
+	arscp_mlist2argv(list);
+	ar_write_archive(bsdar, 'r');
+	arscp_free_argv();
+	arscp_free_mlist(list);
+}
+
+/*
+ * Rename the temporary archive to the target archive.
+ */
+static void
+arscp_save(void)
+{
+	mode_t mask;
+
+	if (target) {
+		if (rename(tmpac, target) < 0)
+			bsdar_errc(bsdar, errno, "rename failed");
+		/*
+		 * Because mkstemp() creates temporary files with mode
+		 * 0600, we set target archive's mode as per the
+		 * process umask.
+		 */
+		mask = umask(0);
+		umask(mask);
+		if (chmod(target, 0666 & ~mask) < 0)
+			bsdar_errc(bsdar, errno, "chmod failed");
+		free(tmpac);
+		free(target);
+		tmpac = NULL;
+		target= NULL;
+		bsdar->filename = NULL;
+	} else
+		bsdar_warnc(bsdar, 0, "no open output archive");
+}
+
+/*
+ * Discard the contents of the current archive. This is achieved by
+ * invoking the 'CREATE' cmd on the current archive.
+ */
+static void
+arscp_clear(void)
+{
+	char		*new_target;
+
+	if (target) {
+		new_target = strdup(target);
+		if (new_target == NULL)
+			bsdar_errc(bsdar, errno, "strdup failed");
+		arscp_create(NULL, new_target);
+	}
+}
+
+/*
+ * Quit ar(1). Note that the 'END' cmd will not 'SAVE' the current
+ * archive before exiting.
+ */
+static void
+arscp_end(int eval)
+{
+
+	if (target)
+		free(target);
+	if (tmpac) {
+		if (unlink(tmpac) == -1)
+			bsdar_errc(bsdar, errno, "unlink %s failed", tmpac);
+		free(tmpac);
+	}
+
+	exit(eval);
+}
+
+/*
+ * Check if a target was specified, i.e, whether an 'OPEN' or 'CREATE'
+ * had been issued by the user.
+ */
+static int
+arscp_target_exist(void)
+{
+
+	if (target)
+		return (1);
+
+	bsdar_warnc(bsdar, 0, "no open output archive");
+	return (0);
+}
+
+/*
+ * Construct the list of modules.
+ */
+static struct list *
+arscp_mlist(struct list *list, char *str)
+{
+	struct list *l;
+
+	l = malloc(sizeof(*l));
+	if (l == NULL)
+		bsdar_errc(bsdar, errno, "malloc failed");
+	l->str = str;
+	l->next = list;
+
+	return (l);
+}
+
+/*
+ * Calculate the length of an mlist.
+ */
+static int
+arscp_mlist_len(struct list *list)
+{
+	int len;
+
+	for(len = 0; list; list = list->next)
+		len++;
+
+	return (len);
+}
+
+/*
+ * Free the space allocated for a module list.
+ */
+static void
+arscp_free_mlist(struct list *list)
+{
+	struct list *l;
+
+	/* Note: list->str was freed in arscp_free_argv(). */
+	for(; list; list = l) {
+		l = list->next;
+		free(list);
+	}
+}
+
+/*
+ * Convert a module list to an 'argv' array.
+ */
+static void
+arscp_mlist2argv(struct list *list)
+{
+	char	**argv;
+	int	  i, n;
+
+	n = arscp_mlist_len(list);
+	argv = malloc(n * sizeof(*argv));
+	if (argv == NULL)
+		bsdar_errc(bsdar, errno, "malloc failed");
+
+	/* Note that module names are stored in reverse order. */
+	for(i = n - 1; i >= 0; i--, list = list->next) {
+		if (list == NULL)
+			bsdar_errc(bsdar, errno, "invalid mlist");
+		argv[i] = list->str;
+	}
+
+	bsdar->argc = n;
+	bsdar->argv = argv;
+}
+
+/*
+ * Free the space allocated for an argv array and its elements.
+ */
+static void
+arscp_free_argv(void)
+{
+	int i;
+
+	for(i = 0; i < bsdar->argc; i++)
+		free(bsdar->argv[i]);
+
+	free(bsdar->argv);
+}
+
+/*
+ * Show a prompt if we are in interactive mode.
+ */
+static void
+arscp_prompt(void)
+{
+
+	if (interactive) {
+		printf("AR >");
+		fflush(stdout);
+	}
+}
+
+/*
+ * The main function implementing script mode.
+ */
+void
+ar_mode_script(struct bsdar *ar)
+{
+
+	bsdar = ar;
+	interactive = isatty(fileno(stdin));
+	while(yyparse()) {
+		if (!interactive)
+			arscp_end(EXIT_FAILURE);
+	}
+
+	/* Script ends without END */
+	arscp_end(EXIT_SUCCESS);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/ar/ar.1	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,624 @@
+.\" Copyright (c) 2007,2009-2012 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: ar.1 3230 2015-07-27 17:11:38Z emaste $
+.\"
+.Dd July 27, 2015
+.Os
+.Dt AR 1
+.Sh NAME
+.Nm ar
+.Nd manage archives
+.Sh SYNOPSIS
+.Nm
+.Fl d
+.Op Fl T
+.Op Fl f
+.Op Fl j
+.Op Fl v
+.Op Fl z
+.Ar archive
+.Ar
+.Nm
+.Fl m
+.Op Fl T
+.Op Fl a Ar position-after
+.Op Fl b Ar position-before
+.Op Fl f
+.Op Fl i Ar position-before
+.Op Fl j
+.Op Fl s | Fl S
+.Op Fl z
+.Ar archive
+.Ar
+.Nm
+.Fl p
+.Op Fl T
+.Op Fl f
+.Op Fl v
+.Ar archive
+.Op Ar
+.Nm
+.Fl q
+.Op Fl T
+.Op Fl c
+.Op Fl D
+.Op Fl f
+.Op Fl F Ar flavor | Fl -flavor Ar flavor
+.Op Fl s | Fl S
+.Op Fl U
+.Op Fl v
+.Op Fl z
+.Ar archive
+.Ar
+.Nm
+.Fl r
+.Op Fl T
+.Op Fl a Ar position-after
+.Op Fl b Ar position-before
+.Op Fl c
+.Op Fl D
+.Op Fl f
+.Op Fl F Ar flavor | Fl -flavor Ar flavor
+.Op Fl i Ar position-before
+.Op Fl j
+.Op Fl s | Fl S
+.Op Fl u
+.Op Fl U
+.Op Fl v
+.Op Fl z
+.Ar archive
+.Ar
+.Nm
+.Fl s
+.Op Fl D
+.Op Fl j
+.Op Fl U
+.Op Fl z
+.Ar archive
+.Nm
+.Fl t
+.Op Fl f
+.Op Fl T
+.Op Fl v
+.Ar archive
+.Op Ar
+.Nm
+.Fl x
+.Op Fl C
+.Op Fl T
+.Op Fl f
+.Op Fl o
+.Op Fl u
+.Op Fl v
+.Ar archive
+.Op Ar
+.Nm
+.Fl M
+.Nm
+.Fl V
+.Sh DESCRIPTION
+The
+.Nm
+utility creates and maintains groups of files combined into an
+archive.
+Once an archive has been created, new files can be added to it, and
+existing files can be extracted, deleted or replaced.
+.Pp
+Files are named in the archive by their last file name component,
+so if a file referenced by a path containing a
+.Dq /
+is archived, it will be named by the last component of the path.
+Similarly when matching paths listed on the command line against
+file names stored in the archive, only the last component of the
+path will be compared.
+.Pp
+The normal use of
+.Nm
+is for the creation and maintenance of libraries suitable for use
+with the link editor
+.Xr ld 1 ,
+although it is not restricted to this purpose.
+The
+.Nm
+utility can create and manage an archive symbol table (see
+.Xr ar 5 )
+used to speed up link editing operations.
+If a symbol table is present in an archive, it will be
+kept up-to-date by subsequent operations on the archive.
+.Sh OPTIONS
+The
+.Nm
+utility supports the following options:
+.Bl -tag -width indent
+.It Fl a Ar member-after
+When used with option
+.Fl m
+this option specifies that the archive members specified by
+arguments
+.Ar
+are moved to after the archive member named by argument
+.Ar member-after .
+When used with option
+.Fl r
+this option specifies that the files specified by arguments
+.Ar
+are added after the archive member named by argument
+.Ar member-after .
+.It Fl b Ar member-before
+When used with option
+.Fl m
+this option specifies that the archive members specified by
+arguments
+.Ar
+are moved to before the archive member named by argument
+.Ar member-before .
+When used with option
+.Fl r
+this option specifies that the files specified by arguments
+.Ar
+are added before the archive member named by argument
+.Ar member-before .
+.It Fl c
+Suppress the informational message printed when a new archive is
+created using the
+.Fl r
+and
+.Fl q
+options.
+.It Fl C
+Prevent extracted files from replacing like-named files
+in the file system.
+.It Fl d
+Delete the members named by arguments
+.Ar
+from the archive specified by argument
+.Ar archive .
+The archive's symbol table, if present, is updated to reflect
+the new contents of the archive.
+.It Fl D
+When used in combination with the
+.Fl r
+or
+.Fl q
+option, insert 0's instead of the real mtime, uid and gid values
+and 0644 instead of file mode from the members named by arguments
+.Ar .
+This ensures that checksums on the resulting archives are reproducible
+when member contents are identical.
+If multiple
+.Fl D
+and
+.Fl U
+options are specified on the command line, the final one takes precedence.
+.It Fl f
+Synonymous with option
+.Fl T .
+.It Fl F Ar flavor | Fl -flavor Ar flavor
+Create archives with the specified archive format.
+Legal values for argument
+.Ar flavor
+are:
+.Bl -tag -width indent -compact
+.It Ar bsd
+Create BSD format archives.
+.It Ar gnu
+An alias for
+.Ar svr4 .
+.It Ar svr4
+Create SVR4 format archives.
+.El
+If this option is not specified,
+.Nm
+will create archives using the SVR4 format.
+.It Fl i Ar member-before
+Synonymous with option
+.Fl b .
+.It Fl j
+This option is accepted for compatibility with the
+.Tn FreeBSD
+version of the
+.Nm
+utility, but is ignored.
+.It Fl l
+This option is accepted for compatibility with GNU
+.Xr ar 1 ,
+but is ignored.
+.It Fl m
+Move archive members specified by arguments
+.Ar
+within the archive.
+If a position has been specified by one of the
+.Fl a ,
+.Fl b
+or
+.Fl i
+options, the members are moved to before or after the specified
+position.
+If no position has been specified, the specified members are moved
+to the end of the archive.
+If the archive has a symbol table, it is updated to reflect the
+new contents of the archive.
+.It Fl M
+Read and execute MRI librarian commands from standard input.
+The commands understood by the
+.Nm
+utility are described in the section
+.Sx "MRI Librarian Commands" .
+.It Fl o
+Preserve the original modification times of members when extracting
+them.
+.It Fl p
+Write the contents of the specified archive members named by
+arguments
+.Ar
+to standard output.
+If no members were specified, the contents of all the files in the
+archive are written in the order they appear in the archive.
+.It Fl q
+Append the files specified by arguments
+.Ar
+to the archive specified by argument
+.Ar archive
+without checking if the files already exist in the archive.
+The archive symbol table will be updated as needed.
+If the file specified by the argument
+.Ar archive
+does not already exist, a new archive will be created.
+.It Fl r
+Replace (add) the files specified by arguments
+.Ar
+in the archive specified by argument
+.Ar archive ,
+creating the archive if necessary.
+Replacing existing members will not change the order of members within
+the archive.
+If a file named in arguments
+.Ar
+does not exist, existing members in the archive that match that
+name are not changed.
+New files are added to the end of the archive unless one of the
+positioning options
+.Fl a ,
+.Fl b
+or
+.Fl i
+is specified.
+The archive symbol table, if it exists, is updated to reflect the
+new state of the archive.
+.It Fl s
+Add an archive symbol table (see
+.Xr ar 5 )
+to the archive specified by argument
+.Ar archive .
+Invoking
+.Nm
+with the
+.Fl s
+option alone is equivalent to invoking
+.Xr ranlib 1 .
+.It Fl S
+Do not generate an archive symbol table.
+.It Fl t
+For
+.Nm ,
+list the files specified by arguments
+.Ar
+in the order in which they appear in the archive, one per line.
+If no files are specified, all files in the archive are listed.
+.It Fl T
+Use only the first fifteen characters of the archive member name or
+command line file name argument when naming archive members.
+.It Fl u
+Conditionally update the archive or extract members.
+When used with the
+.Fl r
+option, files named by arguments
+.Ar
+will be replaced in the archive if they are newer than their
+archived versions.
+When used with the
+.Fl x
+option, the members specified by arguments
+.Ar
+will be extracted only if they are newer than the corresponding
+files in the file system.
+.It Fl U
+When used in combination with the
+.Fl r
+or
+.Fl q
+option, insert the real mtime, uid and gid, and file mode values
+from the members named by arguments
+.Ar .
+If multiple
+.Fl D
+and
+.Fl U
+options are specified on the command line, the final one takes precedence.
+.It Fl v
+Provide verbose output.
+When used with the
+.Fl d ,
+.Fl m ,
+.Fl q
+or
+.Fl x
+options,
+.Nm
+gives a file-by-file description of the archive modification being
+performed, which consists of three white-space separated fields:
+the option letter, a dash
+.Dq "-" ,
+and the file name.
+When used with the
+.Fl r
+option,
+.Nm
+displays the description as above, but the initial letter is an
+.Dq a
+if the file is added to the archive, or an
+.Dq r
+if the file replaces a file already in the archive.
+When used with the
+.Fl p
+option, the name of the file enclosed in
+.Dq <
+and
+.Dq >
+characters is written to standard output preceded by a single newline
+character and followed by two newline characters.
+The contents of the named file follow the file name.
+When used with the
+.Fl t
+option,
+.Nm
+displays eight whitespace separated fields:
+the file permissions as displayed by
+.Xr strmode 3 ,
+decimal user and group IDs separated by a slash (
+.Dq / Ns ) ,
+the file size in bytes, the file modification time in
+.Xr strftime 3
+format
+.Dq "%b %e %H:%M %Y" ,
+and the name of the file.
+.It Fl V
+Print a version identifier and exit.
+.It Fl x
+Extract archive members specified by arguments
+.Ar
+into the current directory.
+If no members have been specified, extract all members of the archive.
+If the file corresponding to an extracted member does not exist it
+will be created.
+If the file corresponding to an extracted member does exist, its owner
+and group will not be changed while its contents will be overwritten
+and its permissions will set to that entered in the archive.
+The file's access and modification time would be that of the time
+of extraction unless the
+.Fl o
+option was specified.
+.It Fl z
+This option is accepted for compatibility with the
+.Tn FreeBSD
+version of the
+.Nm
+utility, but is ignored.
+.El
+.Ss "MRI Librarian Commands"
+If the
+.Fl M
+option is specified, the
+.Nm
+utility will read and execute commands from its standard input.
+If standard input is a terminal, the
+.Nm
+utility will display the prompt
+.Dq Li "AR >"
+before reading a line, and will continue operation even if errors are
+encountered.
+If standard input is not a terminal, the
+.Nm
+utility will not display a prompt and will terminate execution on
+encountering an error.
+.Pp
+Each input line contains a single command.
+Words in an input line are separated by whitespace characters.
+The first word of the line is the command, the remaining words are
+the arguments to the command.
+The command word may be specified in either case.
+Arguments may be separated by commas or blanks.
+.Pp
+Empty lines are allowed and are ignored.
+Long lines are continued by ending them with the
+.Dq Li +
+character.
+.Pp
+The
+.Dq Li *
+and
+.Dq Li "\;"
+characters start a comment.
+Comments extend till the end of the line.
+.Pp
+When executing an MRI librarian script the
+.Nm
+utility works on a temporary copy of an archive.
+Changes to the copy are made permanent using the
+.Ic save
+command.
+.Pp
+Commands understood by the
+.Nm
+utility are:
+.Bl -tag -width indent
+.It Ic addlib Ar archive | Ic addlib Ar archive Pq Ar member Oo Li , Ar member Oc Ns ...
+Add the contents of the archive named by argument
+.Ar archive
+to the current archive.
+If specific members are named using the arguments
+.Ar member ,
+then those members are added to the current archive.
+If no members are specified, the entire contents of the archive
+are added to the current archive.
+.It Ic addmod Ar member Oo Li , Ar member Oc Ns ...
+Add the files named by arguments
+.Ar member
+to the current archive.
+.It Ic clear
+Discard all the contents of the current archive.
+.It Ic create Ar archive
+Create a new archive named by the argument
+.Ar archive ,
+and makes it the current archive.
+If the named archive already exists, it will be overwritten
+when the
+.Ic save
+command is issued.
+.It Ic delete Ar module Oo Li , Ar member Oc Ns ...
+Delete the modules named by the arguments
+.Ar member
+from the current archive.
+.It Ic directory Ar archive Po Ar member Oo Li , Ar member Oc Ns ... Pc Op Ar outputfile
+List each named module in the archive.
+The format of the output depends on the verbosity setting set using
+the
+.Ic verbose
+command.
+Output is sent to standard output, or to the file specified by
+argument
+.Ar outputfile .
+.It Ic end
+Exit successfully from the
+.Nm
+utility.
+Any unsaved changes to the current archive will be discarded.
+.It Ic extract Ar member Oo Li , Ar member Oc Ns ...
+Extract the members named by the arguments
+.Ar member
+from the current archive.
+.It Ic list
+Display the contents of the current archive in verbose style.
+.It Ic open Ar archive
+Open the archive named by argument
+.Ar archive
+and make it the current archive.
+.It Ic replace Ar member Oo Li , Ar member Oc Ns ...
+Replace named members in the current archive with the files specified
+by arguments
+.Ar member .
+The files must be present in the current directory and the named
+modules must already exist in the current archive.
+.It Ic save
+Commit all changes to the current archive.
+.It Ic verbose
+Toggle the verbosity of the
+.Ic directory
+command.
+.El
+.Sh EXAMPLES
+To create a new archive
+.Pa ex.a
+containing three files
+.Pa ex1.o ,
+.Pa ex2.o
+and
+.Pa ex3.o ,
+use:
+.Dl "ar -rc ex.a ex1.o ex2.o ex3.o"
+.Pp
+To add an archive symbol table to an existing archive
+.Pa ex.a ,
+use:
+.Dl "ar -s ex.a"
+.Pp
+To delete file
+.Pa ex1.o
+from archive
+.Pa ex.a ,
+use:
+.D1 "ar -d ex.a ex1.o"
+.Pp
+To verbosely list the contents of archive
+.Pa ex.a ,
+use:
+.D1 "ar -tv ex.a"
+.Pp
+To create a new archive
+.Pa ex.a
+containing the files
+.Pa ex1.o ,
+and
+.Pa ex2.o ,
+using MRI librarian commands, use the following script:
+.Bd -literal -offset indent
+create ex.a		 * specify the output archive
+addmod ex1.o ex2.o	 * add modules
+save			 * save pending changes
+end			 * exit the utility
+.Ed
+.Sh DIAGNOSTICS
+.Ex -std
+.Sh SEE ALSO
+.Xr ld 1 ,
+.Xr ranlib 1 ,
+.Xr archive 3 ,
+.Xr elf 3 ,
+.Xr strftime 3 ,
+.Xr strmode 3 ,
+.Xr ar 5
+.Sh STANDARDS COMPLIANCE
+The
+.Nm
+utility's support for the
+.Fl a ,
+.Fl b ,
+.Fl c ,
+.Fl i ,
+.Fl m ,
+.Fl p ,
+.Fl q ,
+.Fl r ,
+.Fl s ,
+.Fl t ,
+.Fl u ,
+.Fl v ,
+.Fl C
+and
+.Fl T
+options is believed to be compliant with
+.St -p1003.2 .
+.Sh HISTORY
+An
+.Nm
+command first appeared in AT&T UNIX Version 1.
+In
+.Fx 8.0 ,
+.An Kai Wang Aq Mt kaiw@FreeBSD.org
+reimplemented
+.Nm
+using the
+.Lb libarchive
+and the
+.Lb libelf .
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/ar/ar.5	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,327 @@
+.\" Copyright (c) 2010 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: ar.5 3182 2015-04-10 16:08:10Z emaste $
+.\"
+.Dd November 28, 2010
+.Os
+.Dt AR 5
+.Sh NAME
+.Nm ar
+.Nd archive file format for
+.Xr ar 1
+and
+.Xr ranlib 1
+.Sh SYNOPSIS
+.In ar.h
+.Sh DESCRIPTION
+.Xr ar 1
+archives are created and managed by the
+.Xr ar 1
+and
+.Xr ranlib 1
+utilities.
+These archives are typically used during program development to
+hold libraries of program objects.
+An
+.Xr ar 1
+archive is contained in a single operating system file.
+.Pp
+This manual page documents two variants of the
+.Xr ar 1
+archive format: the BSD archive format, and the SVR4/GNU archive
+format.
+.Pp
+In both variants the archive file starts with an identifying byte
+sequence of the seven ASCII characters
+.Sq Li "!<arch>"
+followed by a ASCII linefeed character
+.Po
+see the constant
+.Dq ARMAG
+in the header file
+.In ar.h
+.Pc .
+.Pp
+Archive members follow the initial identifying byte sequence.
+Each archive member is prefixed by a fixed size header describing the
+file attributes associated with the member.
+.Ss "Archive Headers"
+An archive header describes the file attributes for the archive member that
+follows it.
+The
+.Xr ar 5
+format only supports a limited number of attributes: the file name,
+the file creation time stamp, the uid and gid of the creator, the file
+mode and the file size.
+.Pp
+Archive headers are placed at an even byte offset in the archive file.
+If the data for an archive member ends at an odd byte offset, then a
+padding byte with value 0x0A is used to position the next archive
+header on an even byte offset.
+.Pp
+An archive header comprises the following fixed sized fields:
+.Bl -tag -width "Li ar_name"
+.It Ar ar_name
+(16 bytes) The file name of the archive member.
+The format of this field varies between the BSD and SVR4/GNU formats and
+is described in more detail in the section
+.Sx "Representing File Names"
+below.
+.It Ar ar_date
+(12 bytes) The file modification time for the member in seconds since the
+epoch, encoded as a decimal number.
+.It Ar ar_uid
+(6 bytes) The uid associated with the archive member, encoded as a
+decimal number.
+.It Ar ar_gid
+(6 bytes) The gid associated with the archive member, encoded as a
+decimal number.
+.It Ar ar_mode
+(8 bytes) The file mode for the archive member, encoded as an octal
+number.
+.It Ar ar_size
+(10 bytes) In the SVR4/GNU archive format this field holds the size in
+bytes of the archive member, encoded as a decimal number.
+In the BSD archive format, for short file names, this field
+holds the size in bytes of the archive member, encoded as a decimal
+number.
+For long file names
+.Po
+see
+.Sx "Representing File Names"
+below
+.Pc ,
+the field contains the combined size of the
+archive member and its file name, encoded as a decimal number.
+.It Ar ar_fmag
+(2 bytes) This field holds 2 bytes with values 0x96 and 0x0A
+respectively, marking the end of the header.
+.El
+.Pp
+Unused bytes in the fields of an archive header are set to the value
+0x20.
+.Ss "Representing File Names"
+The BSD and SVR4/GNU variants use different schemes for encoding file
+names for members.
+.Bl -tag -width "SVR4/GNU"
+.It "BSD"
+File names that are up to 16 bytes long and which do not contain
+embedded spaces are stored directly in the
+.Ar ar_name
+field of the archive header.
+File names that are either longer than 16 bytes or which contain
+embedded spaces are stored immediately after the archive header
+and the
+.Ar ar_name
+field of the archive header is set to the string
+.Dq "#1/"
+followed by a decimal representation of the number of bytes needed for
+the file name.
+In addition, the
+.Ar ar_size
+field of the archive header is set to the decimal representation of
+the combined sizes of the archive member and the file name.
+The file contents of the member follows the file name without further
+padding.
+.Pp
+As an example, if the file name for a member was
+.Dq "A B"
+and its contents was the string
+.Dq "C D" ,
+then the
+.Ar ar_name
+field of the header would contain
+.Dq Li "#1/3" ,
+the
+.Ar ar_size
+field of the header would contain
+.Dq Li 6 ,
+and the bytes immediately following the header would be 0x41, 0x20,
+0x42, 0x43, 0x20 and 0x44
+.Po
+ASCII
+.Dq "A BC D"
+.Pc .
+.It "SVR4/GNU"
+File names that are up to 15 characters long are stored directly in the
+.Ar ar_name
+field of the header, terminated by a
+.Dq Li /
+character.
+.Pp
+If the file name is larger than would fit in space for the
+.Ar ar_name
+field, then the actual file name is kept in the archive
+string table
+.Po
+see
+.Sx "Archive String Tables"
+below
+.Pc ,
+and the decimal offset of the file name in the string table is stored
+in the
+.Ar ar_name
+field, prefixed by a
+.Dq Li /
+character.
+.Pp
+As an example, if the real file name has been stored at offset 768 in
+the archive string table, the
+.Ar ar_name
+field of the header will contain the string
+.Dq /768 .
+.El
+.Ss "Special Archive Members"
+The following archive members are special.
+.Bl -tag -width indent
+.It Dq Li /
+In the SVR4/GNU variant of the archive format, the archive member with
+name
+.Dq Li /
+denotes an archive symbol table.
+If present, this member will be the very first member in the
+archive.
+.It Dq Li //
+In the SVR4/GNU variant of the archive format, the archive member with
+name
+.Dq Li //
+denotes the archive string table.
+This special member is used to hold filenames that do not fit in the
+file name field of the header
+.Po
+see
+.Sx "Representing File Names"
+above
+.Pc .
+If present, this member immediately follows the archive symbol table
+if an archive symbol table is present, or is the first member otherwise.
+.It Dq Li "__.SYMDEF"
+This special member contains the archive symbol table in the BSD
+variant of the archive format.
+If present, this member will be the very first member in the
+archive.
+.El
+.Ss "Archive String Tables"
+An archive string table is used in the SVR4/GNU archive format to hold
+file names that are too large to fit into the constraints of the
+.Ar ar_name
+field of the archive header.
+An archive string table contains a sequence of file names.
+Each file name in the archive string table is terminated by the
+byte sequence 0x2F, 0x0A
+.Po
+the ASCII string
+.Dq "/\en"
+.Pc .
+No padding is used to separate adjacent file names.
+.Ss "Archive Symbol Tables"
+Archive symbol tables are used to speed up link editing by providing a
+mapping between the program symbols defined in the archive
+and the corresponding archive members.
+Archive symbol tables are managed by the
+.Xr ranlib 1
+utility.
+.Pp
+The format of archive symbol tables is as follows:
+.Bl -tag -width "SVR4/GNU"
+.It BSD
+In the BSD archive format, the archive symbol table comprises
+of two parts: a part containing an array of
+.Vt "struct ranlib"
+descriptors, followed by a part containing a symbol string table.
+The sizes and layout of the structures that make up a BSD format
+archive symbol table are machine dependent.
+.Pp
+The part containing
+.Vt "struct ranlib"
+descriptors begins with a field containing the size in bytes of the
+array of
+.Vt "struct ranlib"
+descriptors encoded as a C
+.Vt long
+value.
+.Pp
+The array of
+.Vt "struct ranlib"
+descriptors follows the size field.
+Each
+.Vt "struct ranlib"
+descriptor describes one symbol.
+.Pp
+A
+.Vt "struct ranlib"
+descriptor comprises two fields:
+.Bl -tag -width "Ar ran_strx" -compact
+.It Ar ran_strx
+.Pq C Vt long
+This field contains the zero-based offset of the symbol name in the
+symbol string table.
+.It Ar ran_off
+.Pq C Vt long
+This field is the file offset to the archive header for the archive
+member defining the symbol.
+.El
+.Pp
+The part containing the symbol string table begins with a field
+containing the size in bytes of the string table, encoded as a C
+.Vt long
+value.
+This string table follows the size field, and contains
+NUL-terminated strings for the symbols in the symbol table.
+.It SVR4/GNU
+In the SVR4/GNU archive format, the archive symbol table starts with a
+4-byte binary value containing the number of entries contained in the
+archive symbol table.
+This count of entries is stored most significant byte first.
+.Pp
+Next, there are
+.Ar count
+4-byte numbers, each stored most significant byte first.
+Each number is a binary offset to the archive header for the member in
+the archive file for the corresponding symbol table entry.
+.Pp
+After the binary offset values, there are
+.Ar count
+NUL-terminated strings in sequence, holding the symbol names for
+the corresponding symbol table entries.
+.El
+.Sh STANDARDS COMPLIANCE
+The
+.Xr ar 1
+archive format is not currently specified by a standard.
+.Pp
+This manual page documents the
+.Xr ar 1
+archive formats used by the
+.Bx 4.4
+and
+.Ux SVR4
+operating system releases.
+.Sh SEE ALSO
+.Xr ar 1 ,
+.Xr ld 1 ,
+.Xr ranlib 1 ,
+.Xr elf 3 ,
+.Xr elf_getarsym 3 ,
+.Xr elf_rand 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/ar/ar.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,441 @@
+/*-
+ * Copyright (c) 2007 Kai Wang
+ * Copyright (c) 2007 Tim Kientzle
+ * Copyright (c) 2007 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Hugh Smith at The University of Guelph.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <archive.h>
+#include <errno.h>
+#include <getopt.h>
+#include <libelftc.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "ar.h"
+
+ELFTC_VCSID("$Id: ar.c 3319 2016-01-13 21:37:53Z jkoshy $");
+
+enum options
+{
+	OPTION_HELP
+};
+
+static struct option longopts[] =
+{
+	{"flavor", required_argument, NULL, 'F'},
+	{"help", no_argument, NULL, OPTION_HELP},
+	{"version", no_argument, NULL, 'V'},
+	{NULL, 0, NULL, 0}
+};
+
+static void	bsdar_usage(void);
+static void	ranlib_usage(void);
+static void	set_mode(struct bsdar *bsdar, char opt);
+static void	only_mode(struct bsdar *bsdar, const char *opt,
+		    const char *valid_modes);
+static void	bsdar_version(void);
+
+int
+main(int argc, char **argv)
+{
+	struct bsdar	*bsdar, bsdar_storage;
+	char		*arcmd, *argv1_saved;
+	size_t		 len;
+	int		 i, opt;
+
+	bsdar = &bsdar_storage;
+	memset(bsdar, 0, sizeof(*bsdar));
+
+	arcmd = argv1_saved = NULL;
+	bsdar->output = stdout;
+
+	if ((bsdar->progname = ELFTC_GETPROGNAME()) == NULL)
+		bsdar->progname = "ar";
+
+	if (elf_version(EV_CURRENT) == EV_NONE)
+		bsdar_errc(bsdar, 0, "ELF library initialization failed: %s",
+		    elf_errmsg(-1));
+
+	/*
+	 * Act like ranlib if our name ends in "ranlib"; this
+	 * accommodates names like "arm-freebsd7.1-ranlib",
+	 * "bsdranlib", etc.
+	 */
+	len = strlen(bsdar->progname);
+	if (len >= strlen("ranlib") &&
+	    strcmp(bsdar->progname + len - strlen("ranlib"), "ranlib") == 0) {
+		while ((opt = getopt_long(argc, argv, "tDUV", longopts,
+		    NULL)) != -1) {
+			switch(opt) {
+			case 't':
+				/* Ignored. */
+				break;
+			case 'D':
+				bsdar->options |= AR_D;
+				break;
+			case 'U':
+				bsdar->options &= ~AR_D;
+				break;
+			case 'V':
+				bsdar_version();
+				break;
+			case OPTION_HELP:
+				ranlib_usage();
+			default:
+				ranlib_usage();
+			}
+		}
+		argv += optind;
+		argc -= optind;
+
+		if (*argv == NULL)
+			ranlib_usage();
+
+		bsdar->options |= AR_S;
+		while ((bsdar->filename = *argv++) != NULL)
+			ar_write_archive(bsdar, 's');
+
+		exit(EXIT_SUCCESS);
+	} else {
+		if (argc < 2)
+			bsdar_usage();
+
+		/*
+		 * Tack on a leading '-', for old-style usage.
+		 */
+		if (*argv[1] != '-') {
+			argv1_saved = argv[1];
+			len = strlen(argv[1]) + 2;
+			if ((arcmd = malloc(len)) == NULL)
+				bsdar_errc(bsdar, errno, "malloc failed");
+			(void) snprintf(arcmd, len, "-%s", argv[1]);
+			argv[1] = arcmd;
+		}
+	}
+
+	while ((opt = getopt_long(argc, argv, "abCcdDfF:ijlMmopqrSsTtUuVvxz",
+	    longopts, NULL)) != -1) {
+		switch(opt) {
+		case 'a':
+			bsdar->options |= AR_A;
+			break;
+		case 'b':
+		case 'i':
+			bsdar->options |= AR_B;
+			break;
+		case 'C':
+			bsdar->options |= AR_CC;
+			break;
+		case 'c':
+			bsdar->options |= AR_C;
+			break;
+		case 'd':
+			set_mode(bsdar, opt);
+			break;
+		case 'D':
+			bsdar->options |= AR_D;
+			break;
+		case 'F':
+			if (!strcasecmp(optarg, "svr4") ||
+			    !strcasecmp(optarg, "gnu"))
+				bsdar->options &= ~AR_BSD;
+			else if (!strcasecmp(optarg, "bsd"))
+				bsdar->options |= AR_BSD;
+			else
+				bsdar_usage();
+			break;
+		case 'f':
+		case 'T':
+			bsdar->options |= AR_TR;
+			break;
+		case 'j':
+			/* ignored */
+			break;
+		case 'l':
+			/* ignored, for GNU ar comptibility */
+			break;
+		case 'M':
+			set_mode(bsdar, opt);
+			break;
+		case 'm':
+			set_mode(bsdar, opt);
+			break;
+		case 'o':
+			bsdar->options |= AR_O;
+			break;
+		case 'p':
+			set_mode(bsdar, opt);
+			break;
+		case 'q':
+			set_mode(bsdar, opt);
+			break;
+		case 'r':
+			set_mode(bsdar, opt);
+			break;
+		case 'S':
+			bsdar->options |= AR_SS;
+			break;
+		case 's':
+			bsdar->options |= AR_S;
+			break;
+		case 't':
+			set_mode(bsdar, opt);
+			break;
+		case 'U':
+			bsdar->options &= ~AR_D;
+			break;
+		case 'u':
+			bsdar->options |= AR_U;
+			break;
+		case 'V':
+			bsdar_version();
+			break;
+		case 'v':
+			bsdar->options |= AR_V;
+			break;
+		case 'x':
+			set_mode(bsdar, opt);
+			break;
+		case 'z':
+			/* ignored */
+			break;
+		case OPTION_HELP:
+			bsdar_usage();
+		default:
+			bsdar_usage();
+		}
+	}
+
+	/* Restore argv[1] if we had modified it. */
+	if (arcmd != NULL) {
+		argv[1] = argv1_saved;
+		free(arcmd);
+		arcmd = argv1_saved = NULL;
+	}
+
+	argv += optind;
+	argc -= optind;
+
+	if (*argv == NULL && bsdar->mode != 'M')
+		bsdar_usage();
+
+	if (bsdar->options & AR_A && bsdar->options & AR_B)
+		bsdar_errc(bsdar, 0,
+		    "only one of -a and -[bi] options allowed");
+
+	if (bsdar->options & AR_J && bsdar->options & AR_Z)
+		bsdar_errc(bsdar, 0,
+		    "only one of -j and -z options allowed");
+
+	if (bsdar->options & AR_S && bsdar->options & AR_SS)
+		bsdar_errc(bsdar, 0,
+		    "only one of -s and -S options allowed");
+
+	if (bsdar->options & (AR_A | AR_B)) {
+		if (*argv == NULL)
+			bsdar_errc(bsdar, 0,
+			    "no position operand specified");
+		if ((bsdar->posarg = basename(*argv)) == NULL)
+			bsdar_errc(bsdar, errno,
+			    "basename failed");
+		argc--;
+		argv++;
+	}
+
+	if (bsdar->options & AR_A)
+		only_mode(bsdar, "-a", "mqr");
+	if (bsdar->options & AR_B)
+		only_mode(bsdar, "-b", "mqr");
+	if (bsdar->options & AR_C)
+		only_mode(bsdar, "-c", "qr");
+	if (bsdar->options & AR_CC)
+		only_mode(bsdar, "-C", "x");
+	if (bsdar->options & AR_D)
+		only_mode(bsdar, "-D", "qr");
+	if (bsdar->options & AR_O)
+		only_mode(bsdar, "-o", "x");
+	if (bsdar->options & AR_SS)
+		only_mode(bsdar, "-S", "mqr");
+	if (bsdar->options & AR_U)
+		only_mode(bsdar, "-u", "qrx");
+
+	if (bsdar->mode == 'M') {
+		ar_mode_script(bsdar);
+		exit(EXIT_SUCCESS);
+	}
+
+	if ((bsdar->filename = *argv) == NULL)
+		bsdar_usage();
+
+	bsdar->argc = --argc;
+	bsdar->argv = ++argv;
+
+	if ((!bsdar->mode || strchr("ptx", bsdar->mode)) &&
+	    bsdar->options & AR_S) {
+		ar_write_archive(bsdar, 's');
+		if (!bsdar->mode)
+			exit(EXIT_SUCCESS);
+	}
+
+	switch(bsdar->mode) {
+	case 'd': case 'm': case 'q': case 'r':
+		ar_write_archive(bsdar, bsdar->mode);
+		break;
+
+	case 'p': case 't': case 'x':
+		ar_read_archive(bsdar, bsdar->mode);
+		break;
+	default:
+		bsdar_usage();
+		/* NOTREACHED */
+	}
+
+	for (i = 0; i < bsdar->argc; i++)
+		if (bsdar->argv[i] != NULL)
+			bsdar_warnc(bsdar, 0, "%s: not found in archive",
+			    bsdar->argv[i]);
+
+	exit(EXIT_SUCCESS);
+}
+
+static void
+set_mode(struct bsdar *bsdar, char opt)
+{
+
+	if (bsdar->mode != '\0' && bsdar->mode != opt)
+		bsdar_errc(bsdar, 0, "Can't specify both -%c and -%c",
+		    opt, bsdar->mode);
+	bsdar->mode = opt;
+}
+
+static void
+only_mode(struct bsdar *bsdar, const char *opt, const char *valid_modes)
+{
+
+	if (strchr(valid_modes, bsdar->mode) == NULL)
+		bsdar_errc(bsdar, 0, "Option %s is not permitted in mode -%c",
+		    opt, bsdar->mode);
+}
+
+#define	AR_USAGE_MESSAGE	"\
+Usage: %s <command> [options] archive file...\n\
+  Manage archives.\n\n\
+  Where <command> is one of:\n\
+  -d            Delete members from the archive.\n\
+  -m            Move archive members within the archive.\n\
+  -p            Write the contents of members to standard output.\n\
+  -q            Append files to an archive.\n\
+  -r            Replace (add) files to an archive.\n\
+  -s            Add an archive symbol to an archive.\n\
+  -t            List files in an archive.\n\
+  -x            Extract members from an archive.\n\
+  -M            Execute MRI librarian commands.\n\
+  -V            Print a version identifier and exit.\n\n\
+  Options:\n\
+  -a MEMBER     Add members after the specified member.\n\
+  -b MEMBER | -i MEMBER\n\
+                Add members before the specified member.\n\
+  -c            Do not print a message when creating a new archive.\n\
+  -f | -T       Only use the first fifteen characters of the member name.\n\
+  -j            (This option is accepted, but is ignored).\n\
+  -l            (This option is accepted, but is ignored).\n\
+  -o            Preserve modification times when extracting members.\n\
+  -u            Conditionally update or extract members.\n\
+  -v            Be verbose.\n\
+  -z            (This option is accepted, but is ignored).\n\
+  -C            Do not overwrite existing files in the file system.\n\
+  -D            Use fixed metadata, for consistent archive checksums.\n\
+  -F FORMAT | --flavor=FORMAT\n\
+                Create archives with the specified format.\n\
+  -S            Do not generate an archive symbol table.\n\
+  -U            Use original metadata for archive members.\n"
+
+static void
+bsdar_usage(void)
+{
+	(void) fprintf(stderr, AR_USAGE_MESSAGE, ELFTC_GETPROGNAME());
+	exit(EXIT_FAILURE);
+}
+
+#define	RANLIB_USAGE_MESSAGE	"\
+Usage: %s [options] archive...\n\
+  Update or create archive symbol tables.\n\n\
+  Options:\n\
+  -t              (This option is accepted, but ignored).\n\
+  -D              Use fixed metadata, for consistent archive checksums.\n\
+  -U              Use original metadata, for unique archive checksums.\n\
+  -V              Print a version identifier and exit.\n"
+
+static void
+ranlib_usage(void)
+{
+	(void)fprintf(stderr, RANLIB_USAGE_MESSAGE, ELFTC_GETPROGNAME());
+	exit(EXIT_FAILURE);
+}
+
+static void
+bsdar_version(void)
+{
+	(void)printf("%s (%s, %s)\n", ELFTC_GETPROGNAME(), archive_version_string(),
+	    elftc_version());
+	exit(EXIT_SUCCESS);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/ar/ar.h	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,143 @@
+/*-
+ * Copyright (c) 2007 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: ar.h 2496 2012-04-24 02:33:40Z jkoshy $
+ */
+
+#include <libelf.h>
+
+#include "_elftc.h"
+
+/*
+ * ar(1) options.
+ */
+#define AR_A	0x0001		/* position-after */
+#define AR_B	0x0002		/* position-before */
+#define AR_C	0x0004		/* creating new archive */
+#define AR_CC	0x0008		/* do not overwrite when extracting */
+#define AR_J	0x0010		/* bzip2 compression */
+#define AR_O	0x0020		/* preserve original mtime when extracting */
+#define AR_S	0x0040		/* write archive symbol table */
+#define AR_SS	0x0080		/* do not write archive symbol table */
+#define AR_TR	0x0100		/* only keep first 15 chars for member name */
+#define AR_U	0x0200		/* only extract or update newer members.*/
+#define AR_V	0x0400		/* verbose mode */
+#define AR_Z	0x0800		/* gzip compression */
+#define AR_D	0x1000		/* insert dummy mode, mtime, uid and gid */
+#define AR_BSD	0x2000		/* use the BSD archive format */
+
+#define DEF_BLKSZ 10240		/* default block size */
+
+/* Special names. */
+
+#define	AR_STRINGTAB_NAME_SVR4	"//"
+#define	AR_SYMTAB_NAME_BSD	"__.SYMDEF"
+#define	AR_SYMTAB_NAME_SVR4	"/"
+
+/*
+ * Convenient wrapper for general libarchive error handling.
+ */
+#define	AC(CALL) do {					\
+	if ((CALL))					\
+		bsdar_errc(bsdar, 0, "%s",		\
+		    archive_error_string(a));		\
+} while (0)
+
+/*
+ * The 'ACV' wrapper is used for libarchive APIs that changed from
+ * returning 'void' to returning an 'int' in later versions of libarchive.
+ */
+#if	ARCHIVE_VERSION_NUMBER >= 2000000
+#define	ACV(CALL)	AC(CALL)
+#else
+#define	ACV(CALL)	do {				\
+		(CALL);					\
+	} while (0)
+#endif
+
+/*
+ * In-memory representation of archive member(object).
+ */
+struct ar_obj {
+	Elf		 *elf;		/* object file descriptor */
+	char		 *name;		/* member name */
+	uid_t		  uid;		/* user id */
+	gid_t		  gid;		/* group id */
+	mode_t		  md;		/* octal file permissions */
+	size_t		  size;		/* member size */
+	time_t		  mtime;	/* modification time */
+	dev_t		  dev;		/* inode's device */
+	ino_t		  ino;		/* inode's number */
+
+	TAILQ_ENTRY(ar_obj) objs;
+};
+
+/*
+ * Structure encapsulates the "global" data for "ar" program.
+ */
+struct bsdar {
+	const char	 *filename;	/* archive name. */
+	const char	 *addlib;	/* target of ADDLIB. */
+	const char	 *posarg;	/* position arg for modifiers -a, -b. */
+	char		  mode;		/* program mode */
+	int		  options;	/* command line options */
+	FILE		 *output;	/* default output stream */
+
+	const char	 *progname;	/* program name */
+	int		  argc;
+	char		**argv;
+
+	dev_t		  ar_dev;	/* archive device. */
+	ino_t		  ar_ino;	/* archive inode. */
+
+	/*
+	 * Fields for the archive string table.
+	 */
+	char		 *as;		/* buffer for archive string table. */
+	size_t		  as_sz;	/* current size of as table. */
+	size_t		  as_cap;	/* capacity of as table buffer. */
+
+	/*
+	 * Fields for the archive symbol table.
+	 */
+	uint32_t	  s_cnt;	/* current number of symbols. */
+	uint32_t	 *s_so;		/* symbol offset table. */
+	size_t		  s_so_cap;	/* capacity of so table buffer. */
+	char		 *s_sn;		/* symbol name table */
+	size_t		  s_sn_cap;	/* capacity of sn table buffer. */
+	size_t		  s_sn_sz;	/* current size of sn table. */
+	/* Current member's offset (relative to the end of pseudo members.) */
+	off_t		  rela_off;
+
+	TAILQ_HEAD(, ar_obj) v_obj;	/* object(member) list */
+};
+
+void	ar_mode_script(struct bsdar *ar);
+void	ar_read_archive(struct bsdar *_ar, int _mode);
+void	ar_write_archive(struct bsdar *_ar, int _mode);
+void	bsdar_errc(struct bsdar *, int _code, const char *fmt, ...);
+int	bsdar_is_pseudomember(struct bsdar *_ar, const char *_name);
+const char *bsdar_strmode(mode_t m);
+void	bsdar_warnc(struct bsdar *, int _code, const char *fmt, ...);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/ar/benchmark/acp.sh	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,65 @@
+#!/bin/sh
+# $Id: acp.sh 2086 2011-10-27 05:18:01Z jkoshy $
+
+# This script is adapted from Jan Psota's Tar Comparison Program(TCP).
+
+n=3			# number of repetitions
+AR="bsdar gnuar"	# ar archivers to compare
+
+test $# -ge 2 || {
+    echo "usage: $0 source_dir where_to_place_archive [where_to_extract_it]"
+    exit 0
+}
+
+THISDIR=`/bin/pwd`
+src=$1
+dst=$2/acp.a
+ext=${3:-$2}/acptmp
+test -e $dst -o -e /tmp/acp \
+    && { echo "$dst or /tmp/acp exists, exiting"; exit 1; }
+mkdir -p $ext || exit 1
+
+show_result ()
+{
+    awk -vL="`du -k $dst`" '{printf "%s\t%s\t%s\%10.1d KB/s\n",
+$1, $3, $5, ($1>0?L/$1:0)}' /tmp/acp | sort | head -n 1
+}
+
+test -d $src || { echo "'$src' is not a directory"; exit 1; }
+
+# ar versions
+for ar in $AR; do echo -n "$ar:	"; $ar -V | head -n 1;
+done
+
+echo
+echo "best time of $n repetitions"
+echo -n "		src=$src, "
+echo -n "`du -sh $src | awk '{print $1}'`"
+echo -n " in "
+echo "`find $src | wc -l` files"
+echo "		archive=$dst, extract to $ext"
+
+echo "program	operation	real	user	system	   speed"
+for op in "cru $dst $src/*" "t $dst" "x `basename $dst`"; do
+    for ar in $AR; do
+	echo -n "$ar	"
+	echo $op | grep -q ^cr && echo -n "create		"
+	echo $op | grep -q ^t && echo -n "list		"
+	echo $op | grep -q ^x && echo -n "extract		"
+	num=0
+	while [ $num -lt $n ]; do
+	    echo $op | grep -q ^cr && rm -f $dst
+	    echo $op | grep -q ^x && { rm -rf $ext; mkdir -p $ext
+		cp $dst $ext; cd $ext; }
+	    sync
+	    time $ar $op > /dev/null 2>> /tmp/acp
+	    echo $op | grep -q ^x && cd $THISDIR
+	    num=`expr $num + 1`
+	done
+	show_result
+	rm -rf /tmp/acp
+    done
+    echo
+done
+rm -rf $ext $dst
+rm -f /tmp/acp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/ar/os.FreeBSD.mk	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,2 @@
+DPADD+= ${LIBBZ2}
+LDADD+= -lbz2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/ar/os.Linux.mk	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,9 @@
+.if ${OS_DISTRIBUTION} == "Ubuntu"
+.if ${OS_DISTRIBUTION_VERSION} >= 14
+# Ubuntu Trusty Tahr and later.
+
+# Use the --nounput option to flex(1), to prevent unused functions from
+# being generated.
+LFLAGS += --nounput
+.endif
+.endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/ar/ranlib.1	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,86 @@
+.\" Copyright (c) 2007,2009-2012 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: ranlib.1 3195 2015-05-12 17:22:19Z emaste $
+.\"
+.Dd December 9, 2012
+.Os
+.Dt RANLIB 1
+.Sh NAME
+.Nm ranlib
+.Nd update archive symbol tables
+.Sh SYNOPSIS
+.Nm
+.Op Fl D
+.Op Fl t
+.Ar archive Ns ...
+.Nm
+.Fl V
+.Sh DESCRIPTION
+The
+.Nm ranlib
+utility is used to update an existing archive symbol table in an
+.Xr ar 1
+archive, or to add an archive symbol table to an archive lacking one.
+.Sh OPTIONS
+The
+.Nm
+utility supports the following options:
+.Bl -tag -width indent
+.It Fl D
+Use zeros for the mtime, uid and gid fields, and use mode 0644 for the
+file mode field for all archive member headers.
+This ensures that checksums on the resulting archives are reproducible
+when member contents are identical.
+.It Fl t
+This option is accepted, but is ignored.
+.It Fl V
+Print a version identifier and exit.
+.El
+.Sh EXAMPLES
+To update the archive symbol table for an archive
+.Pa lib.a ,
+use:
+.Dl "ranlib lib.a"
+.Sh DIAGNOSTICS
+.Ex -std
+.Sh SEE ALSO
+.Xr ar 1 ,
+.Xr ld 1 ,
+.Xr archive 3 ,
+.Xr elf 3 ,
+.Xr ar 5
+.Sh HISTORY
+The
+.Nm
+command first appeared in AT&T UNIX Version 7.
+.Pp
+In
+.Fx 8.0 ,
+.An Kai Wang Aq Mt kaiw@FreeBSD.org
+reimplemented
+.Nm
+using the
+.Lb libarchive
+and the
+.Lb libelf .
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/ar/read.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,199 @@
+/*-
+ * Copyright (c) 2007 Kai Wang
+ * Copyright (c) 2007 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <archive.h>
+#include <archive_entry.h>
+#include <assert.h>
+#include <errno.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "ar.h"
+
+ELFTC_VCSID("$Id: read.c 3180 2015-04-09 15:13:57Z emaste $");
+
+/*
+ * Handle read modes: 'x', 't' and 'p'.
+ */
+void
+ar_read_archive(struct bsdar *bsdar, int mode)
+{
+	FILE			 *out;
+	struct archive		 *a;
+	struct archive_entry	 *entry;
+	struct stat		  sb;
+	struct tm		 *tp;
+	const char		 *bname;
+	const char		 *name;
+	mode_t			  md;
+	size_t			  size;
+	time_t			  mtime;
+	uid_t			  uid;
+	gid_t			  gid;
+	char			**av;
+	char			  buf[25];
+	char			  find;
+	int			  i, flags, r;
+
+	assert(mode == 'p' || mode == 't' || mode == 'x');
+
+	if ((a = archive_read_new()) == NULL)
+		bsdar_errc(bsdar, 0, "archive_read_new failed");
+	archive_read_support_format_ar(a);
+	AC(archive_read_open_filename(a, bsdar->filename, DEF_BLKSZ));
+
+	out = bsdar->output;
+
+	for (;;) {
+		r = archive_read_next_header(a, &entry);
+		if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY ||
+		    r == ARCHIVE_FATAL)
+			bsdar_warnc(bsdar, 0, "%s", archive_error_string(a));
+		if (r == ARCHIVE_EOF || r == ARCHIVE_FATAL)
+			break;
+		if (r == ARCHIVE_RETRY) {
+			bsdar_warnc(bsdar, 0, "Retrying...");
+			continue;
+		}
+
+		if (archive_format(a) == ARCHIVE_FORMAT_AR_BSD)
+			bsdar->options |= AR_BSD;
+		else
+			bsdar->options &= ~AR_BSD;
+
+		if ((name = archive_entry_pathname(entry)) == NULL)
+			break;
+
+		/* Skip pseudo members. */
+		if (bsdar_is_pseudomember(bsdar, name))
+			continue;
+
+		if (bsdar->argc > 0) {
+			find = 0;
+			for(i = 0; i < bsdar->argc; i++) {
+				av = &bsdar->argv[i];
+				if (*av == NULL)
+					continue;
+				if ((bname = basename(*av)) == NULL)
+					bsdar_errc(bsdar, errno,
+					    "basename failed");
+				if (strcmp(bname, name) != 0)
+					continue;
+
+				*av = NULL;
+				find = 1;
+				break;
+			}
+			if (!find)
+				continue;
+		}
+
+		if (mode == 't') {
+			if (bsdar->options & AR_V) {
+				md = archive_entry_mode(entry);
+				uid = archive_entry_uid(entry);
+				gid = archive_entry_gid(entry);
+				size = archive_entry_size(entry);
+				mtime = archive_entry_mtime(entry);
+				(void)fprintf(out, "%s %6d/%-6d %8ju ",
+				    bsdar_strmode(md) + 1, uid, gid,
+				    (uintmax_t)size);
+				tp = localtime(&mtime);
+				(void)strftime(buf, sizeof(buf),
+				    "%b %e %H:%M %Y", tp);
+				(void)fprintf(out, "%s %s", buf, name);
+			} else
+				(void)fprintf(out, "%s", name);
+			r = archive_read_data_skip(a);
+			if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY ||
+			    r == ARCHIVE_FATAL) {
+				(void)fprintf(out, "\n");
+				bsdar_warnc(bsdar, 0, "%s",
+				    archive_error_string(a));
+			}
+
+			if (r == ARCHIVE_FATAL)
+				break;
+
+			(void)fprintf(out, "\n");
+		} else {
+			/* mode == 'x' || mode = 'p' */
+			if (mode == 'p') {
+				if (bsdar->options & AR_V) {
+					(void)fprintf(out, "\n<%s>\n\n",
+					    name);
+					fflush(out);
+				}
+				r = archive_read_data_into_fd(a, fileno(out));
+			} else {
+				/* mode == 'x' */
+				if (stat(name, &sb) != 0) {
+					if (errno != ENOENT) {
+						bsdar_warnc(bsdar, 0,
+						    "stat %s failed",
+						    bsdar->filename);
+						continue;
+					}
+				} else {
+					/* stat success, file exist */
+					if (bsdar->options & AR_CC)
+						continue;
+					if (bsdar->options & AR_U &&
+					    archive_entry_mtime(entry) <=
+					    sb.st_mtime)
+						continue;
+				}
+
+				if (bsdar->options & AR_V)
+					(void)fprintf(out, "x - %s\n", name);
+				/* Disallow absolute paths. */
+				if (name[0] == '/') {
+					bsdar_warnc(bsdar, 0,
+					    "Absolute path '%s'", name);
+					continue;
+				}
+				/* Basic path security flags. */
+				flags = ARCHIVE_EXTRACT_SECURE_SYMLINKS |
+	 			    ARCHIVE_EXTRACT_SECURE_NODOTDOT;
+				if (bsdar->options & AR_O)
+					flags |= ARCHIVE_EXTRACT_TIME;
+
+				r = archive_read_extract(a, entry, flags);
+			}
+
+			if (r)
+				bsdar_warnc(bsdar, 0, "%s",
+				    archive_error_string(a));
+		}
+	}
+	AC(archive_read_close(a));
+	ACV(archive_read_free(a));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/ar/util.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,184 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ar.h"
+
+ELFTC_VCSID("$Id: util.c 3174 2015-03-27 17:13:41Z emaste $");
+
+static void	bsdar_vwarnc(struct bsdar *, int code,
+		    const char *fmt, va_list ap);
+static void	bsdar_verrc(struct bsdar *bsdar, int code,
+		    const char *fmt, va_list ap);
+
+static void
+bsdar_vwarnc(struct bsdar *bsdar, int code, const char *fmt, va_list ap)
+{
+
+	fprintf(stderr, "%s: warning: ", bsdar->progname);
+	vfprintf(stderr, fmt, ap);
+	if (code != 0)
+		fprintf(stderr, ": %s", strerror(code));
+	fprintf(stderr, "\n");
+}
+
+void
+bsdar_warnc(struct bsdar *bsdar, int code, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	bsdar_vwarnc(bsdar, code, fmt, ap);
+	va_end(ap);
+}
+
+static void
+bsdar_verrc(struct bsdar *bsdar, int code, const char *fmt, va_list ap)
+{
+
+	fprintf(stderr, "%s: fatal: ", bsdar->progname);
+	vfprintf(stderr, fmt, ap);
+	if (code != 0)
+		fprintf(stderr, ": %s", strerror(code));
+	fprintf(stderr, "\n");
+}
+
+void
+bsdar_errc(struct bsdar *bsdar, int code, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	bsdar_verrc(bsdar, code, fmt, ap);
+	va_end(ap);
+	exit(EXIT_FAILURE);
+}
+
+#define	AR_STRMODE_SIZE	12
+const char *
+bsdar_strmode(mode_t m)
+{
+	static char buf[AR_STRMODE_SIZE];
+
+#if ELFTC_HAVE_STRMODE
+	/* Use the system's strmode(3). */
+	strmode(m, buf);
+	return buf;
+
+#else
+	char c;
+
+	/*
+	 * The first character of the string denotes the type of the
+	 * entry.
+	 */
+	if (S_ISBLK(m))
+		c = 'b';
+	else if (S_ISCHR(m))
+		c = 'c';
+	else if (S_ISDIR(m))
+		c = 'd';
+#if	defined(S_ISFIFO)
+	else if (S_ISFIFO(m))
+		c = 'p';
+#endif
+#if	defined(S_ISLNK)
+	else if (S_ISLNK(m))
+		c = 'l';
+#endif
+	else if (S_ISREG(m))
+		c = '-';
+#if	defined(S_ISSOCK)
+	else if (S_ISSOCK(m))
+		c = 's';
+#endif
+	else
+		c = '?';
+	buf[0] = c;
+
+	/* The next 3 characters show permissions for the owner. */
+	buf[1] = (m & S_IRUSR) ? 'r' : '-';
+	buf[2] = m & S_IWUSR ? 'w' : '-';
+	if (m & S_ISUID)
+		c = (m & S_IXUSR) ? 's' : 'S';
+	else
+		c = (m & S_IXUSR) ? 'x' : '-';
+	buf[3] = c;
+
+	/* The next 3 characters describe permissions for the group. */
+	buf[4] = (m & S_IRGRP) ? 'r' : '-';
+	buf[5] = m & S_IWGRP ? 'w' : '-';
+	if (m & S_ISGID)
+		c = (m & S_IXGRP) ? 's' : 'S';
+	else
+		c = (m & S_IXGRP) ? 'x' : '-';
+	buf[6] = c;
+
+
+	/* The next 3 characters describe permissions for others. */
+	buf[7] = (m & S_IROTH) ? 'r' : '-';
+	buf[8] = m & S_IWOTH ? 'w' : '-';
+	if (m & S_ISVTX)	/* sticky bit */
+		c = (m & S_IXOTH) ? 't' : 'T';
+	else
+		c = (m & S_IXOTH) ? 'x' : '-';
+	buf[9] = c;
+
+	/* End the string with a blank and NUL-termination. */
+	buf[10] = ' ';
+	buf[11] = '\0';
+
+	return buf;
+#endif	/* !ELTC_HAVE_STRMODE */
+}
+
+int
+bsdar_is_pseudomember(struct bsdar *bsdar, const char *name)
+{
+	/*
+	 * The "__.SYMDEF" member is special in the BSD format
+	 * variant.
+	 */
+	if (bsdar->options & AR_BSD)
+		return (strcmp(name, AR_SYMTAB_NAME_BSD) == 0);
+	else
+		/*
+		 * The names "/ " and "// " are special in the SVR4
+		 * variant.
+		 */
+		return (strcmp(name, AR_STRINGTAB_NAME_SVR4) == 0 ||
+		    strcmp(name, AR_SYMTAB_NAME_SVR4) == 0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/ar/write.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,975 @@
+/*-
+ * Copyright (c) 2007 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <archive.h>
+#include <archive_entry.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ar.h"
+
+ELFTC_VCSID("$Id: write.c 3183 2015-04-10 16:18:42Z emaste $");
+
+#define _ARMAG_LEN 8		/* length of the magic string */
+#define _ARHDR_LEN 60		/* length of the archive header */
+#define _INIT_AS_CAP 128	/* initial archive string table size */
+#define _INIT_SYMOFF_CAP (256*(sizeof(uint32_t))) /* initial so table size */
+#define _INIT_SYMNAME_CAP 1024			  /* initial sn table size */
+#define _MAXNAMELEN_SVR4 15	/* max member name length in svr4 variant */
+#define _MAXNAMELEN_BSD  16	/* max member name length in bsd variant */
+#define _TRUNCATE_LEN 15	/* number of bytes to keep for member name */
+
+static void	add_to_ar_str_table(struct bsdar *bsdar, const char *name);
+static void	add_to_ar_sym_table(struct bsdar *bsdar, const char *name);
+static struct ar_obj	*create_obj_from_file(struct bsdar *bsdar,
+		    const char *name, time_t mtime);
+static void	create_symtab_entry(struct bsdar *bsdar, Elf *e);
+static void	free_obj(struct ar_obj *obj);
+static void	insert_obj(struct bsdar *bsdar, struct ar_obj *obj,
+		    struct ar_obj *pos);
+static void	read_objs(struct bsdar *bsdar, const char *archive,
+		    int checkargv);
+static void	write_cleanup(struct bsdar *bsdar);
+static void	write_data(struct bsdar *bsdar, struct archive *a,
+		    const void *buf, size_t s);
+static void	write_objs(struct bsdar *bsdar);
+
+/*
+ * Create an object from a file, and return the created object
+ * descriptor.  Return NULL if either an error occurs, or if the '-u'
+ * option was specified and the member is not newer than the existing
+ * one in the archive.
+ */
+static struct ar_obj *
+create_obj_from_file(struct bsdar *bsdar, const char *name, time_t mtime)
+{
+	struct ar_obj		*obj;
+	struct stat		 sb;
+	const char		*bname;
+	char			*tmpname;
+	int			fd;
+
+	if (name == NULL)
+		return (NULL);
+
+	obj = malloc(sizeof(struct ar_obj));
+	if (obj == NULL)
+		bsdar_errc(bsdar, errno, "malloc failed");
+
+	obj->elf = NULL;
+
+	if ((fd = open(name, O_RDONLY, 0)) < 0) {
+		bsdar_warnc(bsdar, errno, "can't open file: %s", name);
+		free(obj);
+		return (NULL);
+	}
+
+	tmpname = strdup(name);
+	if ((bname = basename(tmpname)) == NULL)
+		bsdar_errc(bsdar, errno, "basename failed");
+	if (bsdar->options & AR_TR && strlen(bname) > _TRUNCATE_LEN) {
+		if ((obj->name = malloc(_TRUNCATE_LEN + 1)) == NULL)
+			bsdar_errc(bsdar, errno, "malloc failed");
+		(void)strncpy(obj->name, bname, _TRUNCATE_LEN);
+		obj->name[_TRUNCATE_LEN] = '\0';
+	} else
+		if ((obj->name = strdup(bname)) == NULL)
+		    bsdar_errc(bsdar, errno, "strdup failed");
+	free(tmpname);
+
+	if (fstat(fd, &sb) < 0) {
+		bsdar_warnc(bsdar, errno, "can't fstat file: %s", obj->name);
+		goto giveup;
+	}
+	if (!S_ISREG(sb.st_mode)) {
+		bsdar_warnc(bsdar, 0, "%s is not an ordinary file", obj->name);
+		goto giveup;
+	}
+
+	if (sb.st_dev == bsdar->ar_dev && sb.st_ino == bsdar->ar_ino) {
+		bsdar_warnc(bsdar, 0, "cannot add archive \"%s\" to itself",
+		    obj->name);
+		goto giveup;
+	}
+
+	/*
+	 * If the '-u' option is specified and member is not newer
+	 * than the existing one, we should not replace the member.
+	 * However, if mtime == 0, i.e., if nonexistent members are to
+	 * be forcibly replaced, then the '-u' option is to be ignored.
+	 */
+	if (mtime != 0 && bsdar->options & AR_U && sb.st_mtime <= mtime)
+		goto giveup;
+
+	/*
+	 * When the '-D' option is specified, the mtime and UID/GID of
+	 * the member will be set to 0, and the file mode will be set
+	 * to 644. This ensures that checksums will match for two
+	 * archives containing identical content.
+	 */
+	if (bsdar->options & AR_D) {
+		obj->uid = 0;
+		obj->gid = 0;
+		obj->mtime = 0;
+		obj->md = S_IFREG | 0644;
+	} else {
+		obj->uid = sb.st_uid;
+		obj->gid = sb.st_gid;
+		obj->mtime = sb.st_mtime;
+		obj->md = sb.st_mode;
+	}
+	obj->size = sb.st_size;
+	obj->dev = sb.st_dev;
+	obj->ino = sb.st_ino;
+
+	if (obj->size == 0) {
+		return (obj);
+	}
+
+	if ((obj->elf = elf_open(fd)) == NULL) {
+		bsdar_warnc(bsdar, 0, "file initialization failed for %s: %s",
+		    obj->name, elf_errmsg(-1));
+		goto giveup;
+	}
+
+	/*
+	 * Read the object fully into memory and close its file
+	 * descriptor.
+	 */
+	if (elf_cntl(obj->elf, ELF_C_FDREAD) < 0) {
+		bsdar_warnc(bsdar, 0, "%s could not be read in: %s",
+		    obj->name, elf_errmsg(-1));
+		goto giveup;
+	}
+
+	if (close(fd) < 0)
+		bsdar_errc(bsdar, errno, "close failed: %s",
+		    obj->name);
+
+	return (obj);
+
+giveup:
+	if (obj->elf)
+		elf_end(obj->elf);
+
+	if (close(fd) < 0)
+		bsdar_errc(bsdar, errno, "close failed: %s",
+		    obj->name);
+	free(obj->name);
+	free(obj);
+	return (NULL);
+}
+
+/*
+ * Free an object and its associated allocations.
+ */
+static void
+free_obj(struct ar_obj *obj)
+{
+	if (obj->elf)
+		elf_end(obj->elf);
+
+	free(obj->name);
+	free(obj);
+}
+
+/*
+ * Insert an object into a list, either before/after the 'pos' obj or
+ * at the end of the list.
+ */
+static void
+insert_obj(struct bsdar *bsdar, struct ar_obj *obj, struct ar_obj *pos)
+{
+	if (obj == NULL)
+		bsdar_errc(bsdar, 0, "try to insert a null obj");
+
+	if (pos == NULL || obj == pos)
+		/*
+		 * If the object to move happens to be the position
+		 * obj, or if there is no position obj, move the
+		 * object to the end.
+		 */
+		goto tail;
+
+	if (bsdar->options & AR_B) {
+		TAILQ_INSERT_BEFORE(pos, obj, objs);
+		return;
+	}
+	if (bsdar->options & AR_A) {
+		TAILQ_INSERT_AFTER(&bsdar->v_obj, pos, obj, objs);
+		return;
+	}
+
+tail:
+	TAILQ_INSERT_TAIL(&bsdar->v_obj, obj, objs);
+
+}
+
+/*
+ * Read objects from archive into the 'v_obj' list. Note that
+ * 'checkargv' is set when read_objs() is used to read objects from
+ * the target of 'ADDLIB' command in ar script mode; in this case the
+ * 'argv' array specifies the members that 'ADDLIB' is to operate on.
+ */
+static void
+read_objs(struct bsdar *bsdar, const char *archive, int checkargv)
+{
+	struct archive		 *a;
+	struct archive_entry	 *entry;
+	struct ar_obj		 *obj;
+	const char		 *name;
+	const char		 *bname;
+	char			 *buff;
+	char			**av;
+	size_t			  size;
+	int			  i, r, find;
+
+	if ((a = archive_read_new()) == NULL)
+		bsdar_errc(bsdar, 0, "archive_read_new failed");
+	archive_read_support_format_ar(a);
+	AC(archive_read_open_filename(a, archive, DEF_BLKSZ));
+	for (;;) {
+		r = archive_read_next_header(a, &entry);
+		if (r == ARCHIVE_FATAL)
+			bsdar_errc(bsdar, 0, "%s", archive_error_string(a));
+		if (r == ARCHIVE_EOF)
+			break;
+		if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY)
+			bsdar_warnc(bsdar, 0, "%s", archive_error_string(a));
+		if (r == ARCHIVE_RETRY) {
+			bsdar_warnc(bsdar, 0, "Retrying...");
+			continue;
+		}
+
+		name = archive_entry_pathname(entry);
+
+		/*
+		 * Skip pseudo members.
+		 */
+		if (bsdar_is_pseudomember(bsdar, name))
+			continue;
+
+		/*
+		 * If 'checkargv' is set, only read those members
+		 * specified in argv.
+		 */
+		if (checkargv && bsdar->argc > 0) {
+			find = 0;
+			for(i = 0; i < bsdar->argc; i++) {
+				av = &bsdar->argv[i];
+				if (*av == NULL)
+					continue;
+				if ((bname = basename(*av)) == NULL)
+					bsdar_errc(bsdar, errno,
+					    "basename failed");
+				if (strcmp(bname, name) != 0)
+					continue;
+
+				*av = NULL;
+				find = 1;
+				break;
+			}
+			if (!find)
+				continue;
+		}
+
+		size = archive_entry_size(entry);
+
+		if (size > 0) {
+			if ((buff = malloc(size)) == NULL)
+				bsdar_errc(bsdar, errno, "malloc failed");
+			if (archive_read_data(a, buff, size) != (ssize_t)size) {
+				bsdar_warnc(bsdar, 0, "%s",
+				    archive_error_string(a));
+				free(buff);
+				continue;
+			}
+		} else
+			buff = NULL;
+
+		obj = malloc(sizeof(struct ar_obj));
+		if (obj == NULL)
+			bsdar_errc(bsdar, errno, "malloc failed");
+		obj->elf = NULL;
+		if (buff) {
+			obj->elf = elf_openmemory(buff, size);
+			if (obj->elf == NULL) {
+				bsdar_warnc(bsdar, 0, "elf_openmemory() "
+				    "failed for %s: %s", name,
+				    elf_errmsg(-1));
+				free(buff);
+				free(obj);
+				continue;
+			}
+		}
+		if ((obj->name = strdup(name)) == NULL)
+			bsdar_errc(bsdar, errno, "strdup failed");
+		obj->size = size;
+		obj->uid = archive_entry_uid(entry);
+		obj->gid = archive_entry_gid(entry);
+		obj->md = archive_entry_mode(entry);
+		obj->mtime = archive_entry_mtime(entry);
+		obj->dev = 0;
+		obj->ino = 0;
+
+		TAILQ_INSERT_TAIL(&bsdar->v_obj, obj, objs);
+	}
+	AC(archive_read_close(a));
+	ACV(archive_read_free(a));
+}
+
+/*
+ * Write an archive.
+ */
+void
+ar_write_archive(struct bsdar *bsdar, int mode)
+{
+	struct ar_obj		 *nobj, *obj, *obj_temp, *pos;
+	struct stat		  sb;
+	const char		 *bname;
+	char			**av;
+	int			  i;
+
+	TAILQ_INIT(&bsdar->v_obj);
+	nobj = NULL;
+	pos = NULL;
+	memset(&sb, 0, sizeof(sb));
+
+	assert(mode == 'A' || mode == 'd' || mode == 'm' || mode == 'q' ||
+	    mode == 'r' || mode == 's');
+
+	/*
+	 * Test if the specified archive exists, to determine
+	 * whether we are creating a new archive.
+	 */
+	if (stat(bsdar->filename, &sb) != 0) {
+		if (errno != ENOENT) {
+			bsdar_warnc(bsdar, 0, "stat %s failed",
+			    bsdar->filename);
+			return;
+		}
+
+		/* We do not create archive in mode 'd', 'm' and 's'.  */
+		if (mode != 'r' && mode != 'q') {
+			bsdar_warnc(bsdar, 0, "%s: no such file",
+			    bsdar->filename);
+			return;
+		}
+
+		/* Issue a message if the '-c' option was not specified. */
+		if (!(bsdar->options & AR_C))
+			bsdar_warnc(bsdar, 0, "creating %s", bsdar->filename);
+		goto new_archive;
+	}
+
+	bsdar->ar_dev = sb.st_dev;
+	bsdar->ar_ino = sb.st_ino;
+
+	/*
+	 * First read members from the existing archive.
+	 */
+	read_objs(bsdar, bsdar->filename, 0);
+
+	/*
+	 * For mode 's', no member will be moved, deleted or replaced.
+	 */
+	if (mode == 's')
+		goto write_objs;
+
+	/*
+	 * For mode 'q', we don't need to adjust existing members either.
+	 * Also, -a, -b and -i are ignored in this mode. New members are
+	 * always inserted at tail.
+	 */
+	if (mode == 'q')
+		goto new_archive;
+
+	/*
+	 * Mode 'A' adds the contents of another archive to the tail
+	 * of current archive. Note that mode 'A' is a special mode
+	 * for the 'ADDLIB' command in ar's script mode. Currently
+	 * there is no option that invokes this function from ar's
+	 * command line.
+	 */
+	if (mode == 'A') {
+		/*
+		 * Read objects from the target archive of the
+		 * 'ADDLIB' command.  If there are members specified in
+		 * 'argv', read those members only, otherwise the
+		 * entire archive will be read.
+		 */
+		read_objs(bsdar, bsdar->addlib, 1);
+		goto write_objs;
+	}
+
+	/*
+	 * Try to find the position member specified by user.
+	 */
+	if (bsdar->options & AR_A || bsdar->options & AR_B) {
+		TAILQ_FOREACH(obj, &bsdar->v_obj, objs) {
+			if (strcmp(obj->name, bsdar->posarg) == 0) {
+				pos = obj;
+				break;
+			}
+		}
+
+		/*
+		 * If we cannot find the position specified by the
+		 * user, silently insert objects at the tail of the
+		 * list.
+		 */
+		if (pos == NULL)
+			bsdar->options &= ~(AR_A | AR_B);
+	}
+
+	for (i = 0; i < bsdar->argc; i++) {
+		av = &bsdar->argv[i];
+
+		TAILQ_FOREACH_SAFE(obj, &bsdar->v_obj, objs, obj_temp) {
+			if ((bname = basename(*av)) == NULL)
+				bsdar_errc(bsdar, errno, "basename failed");
+			if (bsdar->options & AR_TR) {
+				if (strncmp(bname, obj->name, _TRUNCATE_LEN))
+					continue;
+			} else
+				if (strcmp(bname, obj->name) != 0)
+					continue;
+
+			if (mode == 'r') {
+				/*
+				 * If the new member should not
+				 * replace the old one, skip it.
+				 */
+				nobj = create_obj_from_file(bsdar, *av,
+				    obj->mtime);
+				if (nobj == NULL)
+					goto skip_obj;
+			}
+
+			if (bsdar->options & AR_V)
+				(void)fprintf(bsdar->output, "%c - %s\n",
+				    mode, *av);
+
+			TAILQ_REMOVE(&bsdar->v_obj, obj, objs);
+			if (mode == 'd' || mode == 'r')
+				free_obj(obj);
+
+			if (mode == 'm')
+				insert_obj(bsdar, obj, pos);
+			if (mode == 'r')
+				insert_obj(bsdar, nobj, pos);
+
+		skip_obj:
+			*av = NULL;
+			break;
+		}
+
+	}
+
+new_archive:
+	/*
+	 * When operating in mode 'r', directly add the specified
+	 * objects which do not exist in current archive. When
+	 * operating in mode 'q', all objects specified by the command
+	 * line args are appended to the archive, without checking
+	 * existing members in the archive.
+	 */
+	for (i = 0; i < bsdar->argc; i++) {
+		av = &bsdar->argv[i];
+		if (*av != NULL && (mode == 'r' || mode == 'q')) {
+			nobj = create_obj_from_file(bsdar, *av, 0);
+			if (nobj != NULL)
+				insert_obj(bsdar, nobj, pos);
+			if (bsdar->options & AR_V && nobj != NULL)
+				(void)fprintf(bsdar->output, "a - %s\n", *av);
+			*av = NULL;
+		}
+	}
+
+write_objs:
+	write_objs(bsdar);
+	write_cleanup(bsdar);
+}
+
+/*
+ * Release memory.
+ */
+static void
+write_cleanup(struct bsdar *bsdar)
+{
+	struct ar_obj		*obj, *obj_temp;
+
+	TAILQ_FOREACH_SAFE(obj, &bsdar->v_obj, objs, obj_temp) {
+		TAILQ_REMOVE(&bsdar->v_obj, obj, objs);
+		free_obj(obj);
+	}
+
+	free(bsdar->as);
+	free(bsdar->s_so);
+	free(bsdar->s_sn);
+	bsdar->as = NULL;
+	bsdar->s_so = NULL;
+	bsdar->s_sn = NULL;
+}
+
+/*
+ * Wrapper for archive_write_data().
+ */
+static void
+write_data(struct bsdar *bsdar, struct archive *a, const void *buf, size_t s)
+{
+	if (archive_write_data(a, buf, s) != (ssize_t)s)
+		bsdar_errc(bsdar, 0, "%s", archive_error_string(a));
+}
+
+/*
+ * Compute the size of the symbol table for an archive.
+ */
+static size_t
+bsdar_symtab_size(struct bsdar *bsdar)
+{
+	size_t sz;
+
+	if (bsdar->options & AR_BSD) {
+		/*
+		 * A BSD style symbol table has two parts.
+		 * Each part is preceded by its size in bytes,
+		 * encoded as a C 'long'.  In the first part,
+		 * there are 's_cnt' entries, each entry being
+		 * 2 'long's in size.  The second part
+		 * contains a string table.
+		 */
+		sz = 2 * sizeof(long) + (bsdar->s_cnt * 2 * sizeof(long)) +
+		    bsdar->s_sn_sz;
+	} else {
+		/*
+		 * An SVR4 style symbol table comprises of a 32 bit
+		 * number holding the number of entries, followed by
+		 * that many 32-bit offsets, followed by a string
+		 * table.
+		 */
+		sz = sizeof(uint32_t) + bsdar->s_cnt * sizeof(uint32_t) +
+		    bsdar->s_sn_sz;
+	}
+
+	return (sz);
+}
+
+static void
+write_svr4_symtab_entry(struct bsdar *bsdar, struct archive *a)
+{
+	int		nr;
+	uint32_t	i;
+
+	/* Translate offsets to big-endian form. */
+	for (i = 0; i < bsdar->s_cnt; i++)
+		bsdar->s_so[i] = htobe32(bsdar->s_so[i]);
+
+	nr = htobe32(bsdar->s_cnt);
+	write_data(bsdar, a, &nr, sizeof(uint32_t));
+	write_data(bsdar, a, bsdar->s_so, sizeof(uint32_t) *
+	    bsdar->s_cnt);
+	write_data(bsdar, a, bsdar->s_sn, bsdar->s_sn_sz);
+}
+
+static void
+write_bsd_symtab_entry(struct bsdar *bsdar, struct archive *a)
+{
+	long br_sz, br_off, br_strx;
+	char *s;
+	uint32_t i;
+
+	/*
+	 * Write out the size in the byte of the array of 'ranlib'
+	 * descriptors to follow.
+	 */
+
+	br_sz = (long) (bsdar->s_cnt * 2 * sizeof(long));
+	write_data(bsdar, a, &br_sz, sizeof(long));
+
+	/*
+	 * Write out the array of 'ranlib' descriptors.  Each
+	 * descriptor comprises of (a) an offset into the following
+	 * string table and (b) a file offset to the relevant member.
+	 */
+	for (i = 0, s = bsdar->s_sn; i < bsdar->s_cnt; i++) {
+		br_strx = (long) (s - bsdar->s_sn);
+		br_off = (long) bsdar->s_so[i];
+		write_data(bsdar, a, &br_strx, sizeof(long));
+		write_data(bsdar, a, &br_off, sizeof(long));
+
+		/* Find the start of the next symbol in the string table. */
+		while (*s++ != '\0')
+			;
+	}
+
+	/*
+	 * Write out the size of the string table as a 'long',
+	 * followed by the string table itself.
+	 */
+	br_sz = (long) bsdar->s_sn_sz;
+	write_data(bsdar, a, &br_sz, sizeof(long));
+	write_data(bsdar, a, bsdar->s_sn, bsdar->s_sn_sz);
+}
+
+
+/*
+ * Write the resulting archive members.
+ */
+static void
+write_objs(struct bsdar *bsdar)
+{
+	struct ar_obj		*obj;
+	struct archive		*a;
+	struct archive_entry	*entry;
+	size_t s_sz;		/* size of archive symbol table. */
+	size_t pm_sz;		/* size of pseudo members */
+	size_t namelen;		/* size of member name. */
+	size_t obj_sz;		/* size of object + extended header. */
+	int			 i;
+	char			*buf;
+	const char		*entry_name;
+
+	bsdar->rela_off = 0;
+
+	/*
+	 * Create the archive symbol table and the archive string
+	 * table, if needed.
+	 */
+	TAILQ_FOREACH(obj, &bsdar->v_obj, objs) {
+		if (!(bsdar->options & AR_SS) && obj->elf != NULL)
+			create_symtab_entry(bsdar, obj->elf);
+
+		obj_sz = 0;
+		namelen = strlen(obj->name);
+		if (bsdar->options & AR_BSD) {
+			/* Account for the space used by the file name. */
+			if (namelen > _MAXNAMELEN_BSD ||
+			    strchr(obj->name, ' '))
+				obj_sz += namelen;
+		} else if (namelen > _MAXNAMELEN_SVR4)
+			add_to_ar_str_table(bsdar, obj->name);
+
+		obj_sz += obj->size; /* add the actual object size  */
+
+		/* Roundup the final size and add the header length. */
+		bsdar->rela_off += _ARHDR_LEN + obj_sz + (obj_sz & 1);
+	}
+
+	/*
+	 * Pad the symbol name string table. It is treated specially
+	 * because symbol name table should be padded by a '\0', and
+	 * not '\n' as for normal members. The size of the 'sn' table
+	 * includes the pad byte.
+	 */
+	if (bsdar->s_cnt != 0 && bsdar->s_sn_sz % 2 != 0)
+		bsdar->s_sn[bsdar->s_sn_sz++] = '\0';
+
+	/*
+	 * The archive string table is padded by a "\n" like a normal
+	 * member.  The difference is that the size of archive string
+	 * table includes the pad byte, while normal members' size
+	 * fields do not.
+	 */
+	if (bsdar->as != NULL && bsdar->as_sz % 2 != 0)
+		bsdar->as[bsdar->as_sz++] = '\n';
+
+	/*
+	 * If there is a symbol table, calculate the size of pseudo
+	 * members, and convert previously stored relative offsets to
+	 * absolute ones.
+	 *
+	 * absolute_offset = relative_offset + size_of_pseudo_members)
+	 */
+
+	s_sz = bsdar_symtab_size(bsdar);
+	if (bsdar->s_cnt != 0) {
+		pm_sz = _ARMAG_LEN + (_ARHDR_LEN + s_sz);
+		if (bsdar->as != NULL) /* SVR4 archives only */
+			pm_sz += _ARHDR_LEN + bsdar->as_sz;
+		for (i = 0; (size_t) i < bsdar->s_cnt; i++)
+			bsdar->s_so[i] = bsdar->s_so[i] + pm_sz;
+	}
+
+	if ((a = archive_write_new()) == NULL)
+		bsdar_errc(bsdar, 0, "archive_write_new failed");
+
+	if (bsdar->options & AR_BSD)
+		archive_write_set_format_ar_bsd(a);
+	else
+		archive_write_set_format_ar_svr4(a);
+
+	AC(archive_write_open_filename(a, bsdar->filename));
+
+	/*
+	 * Write the archive symbol table, if there is one.  If
+	 * options '-s' was explicitly specified or if we were invoked
+	 * as 'ranlib', write the symbol table even if it is empty.
+	 */
+	if ((bsdar->s_cnt != 0 && !(bsdar->options & AR_SS)) ||
+	    bsdar->options & AR_S) {
+		if (bsdar->options & AR_BSD)
+			entry_name = AR_SYMTAB_NAME_BSD;
+		else
+			entry_name = AR_SYMTAB_NAME_SVR4;
+
+		entry = archive_entry_new();
+		archive_entry_copy_pathname(entry, entry_name);
+		if ((bsdar->options & AR_D) == 0)
+			archive_entry_set_mtime(entry, time(NULL), 0);
+		archive_entry_set_size(entry, s_sz);
+		AC(archive_write_header(a, entry));
+		if (bsdar->options & AR_BSD)
+			write_bsd_symtab_entry(bsdar, a);
+		else
+			write_svr4_symtab_entry(bsdar, a);
+		archive_entry_free(entry);
+	}
+
+	/* Write the archive string table, if any. */
+	if (bsdar->as != NULL) {
+		entry = archive_entry_new();
+		archive_entry_copy_pathname(entry, AR_STRINGTAB_NAME_SVR4);
+		archive_entry_set_size(entry, bsdar->as_sz);
+		AC(archive_write_header(a, entry));
+		write_data(bsdar, a, bsdar->as, bsdar->as_sz);
+		archive_entry_free(entry);
+	}
+
+	/* Write normal members. */
+	TAILQ_FOREACH(obj, &bsdar->v_obj, objs) {
+		if ((buf = elf_rawfile(obj->elf, NULL)) == NULL) {
+			bsdar_warnc(bsdar, 0, "elf_rawfile() failed: %s",
+			    elf_errmsg(-1));
+			continue;
+		}
+
+		entry = archive_entry_new();
+		archive_entry_copy_pathname(entry, obj->name);
+		archive_entry_set_uid(entry, obj->uid);
+		archive_entry_set_gid(entry, obj->gid);
+		archive_entry_set_mode(entry, obj->md);
+		archive_entry_set_size(entry, obj->size);
+		archive_entry_set_mtime(entry, obj->mtime, 0);
+		archive_entry_set_dev(entry, obj->dev);
+		archive_entry_set_ino(entry, obj->ino);
+		archive_entry_set_filetype(entry, AE_IFREG);
+		AC(archive_write_header(a, entry));
+		write_data(bsdar, a, buf, obj->size);
+		archive_entry_free(entry);
+	}
+
+	AC(archive_write_close(a));
+	ACV(archive_write_free(a));
+}
+
+/*
+ * Extract global symbols from ELF binary members.
+ */
+static void
+create_symtab_entry(struct bsdar *bsdar, Elf *e)
+{
+	Elf_Scn		*scn;
+	GElf_Shdr	 shdr;
+	GElf_Sym	 sym;
+	Elf_Data	*data;
+	char		*name;
+	size_t		 n, shstrndx;
+	int		 elferr, tabndx, len, i;
+
+	if (elf_kind(e) != ELF_K_ELF) {
+		/* Silently a ignore non-ELF member. */
+		return;
+	}
+	if (elf_getshstrndx(e, &shstrndx) == 0) {
+		bsdar_warnc(bsdar, 0, "elf_getshstrndx failed: %s",
+		     elf_errmsg(-1));
+		return;
+	}
+
+	tabndx = -1;
+	scn = NULL;
+	while ((scn = elf_nextscn(e, scn)) != NULL) {
+		if (gelf_getshdr(scn, &shdr) != &shdr) {
+			bsdar_warnc(bsdar, 0,
+			    "elf_getshdr failed: %s", elf_errmsg(-1));
+			continue;
+		}
+		if ((name = elf_strptr(e, shstrndx, shdr.sh_name)) == NULL) {
+			bsdar_warnc(bsdar, 0,
+			    "elf_strptr failed: %s", elf_errmsg(-1));
+			continue;
+		}
+		if (strcmp(name, ".strtab") == 0) {
+			tabndx = elf_ndxscn(scn);
+			break;
+		}
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		bsdar_warnc(bsdar, 0, "elf_nextscn failed: %s",
+		     elf_errmsg(elferr));
+	if (tabndx == -1) {
+		bsdar_warnc(bsdar, 0, "can't find .strtab section");
+		return;
+	}
+
+	scn = NULL;
+	while ((scn = elf_nextscn(e, scn)) != NULL) {
+		if (gelf_getshdr(scn, &shdr) != &shdr) {
+			bsdar_warnc(bsdar, 0, "elf_getshdr failed: %s",
+			    elf_errmsg(-1));
+			continue;
+		}
+		if (shdr.sh_type != SHT_SYMTAB)
+			continue;
+
+		data = NULL;
+		n = 0;
+		while (n < shdr.sh_size &&
+		    (data = elf_getdata(scn, data)) != NULL) {
+			len = data->d_size / shdr.sh_entsize;
+			for (i = 0; i < len; i++) {
+				if (gelf_getsym(data, i, &sym) != &sym) {
+					bsdar_warnc(bsdar, 0,
+					    "gelf_getsym failed: %s",
+					     elf_errmsg(-1));
+					continue;
+				}
+
+				/* Keep only global and weak symbols. */
+				if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL &&
+				    GELF_ST_BIND(sym.st_info) != STB_WEAK)
+					continue;
+
+				/* Keep only defined symbols. */
+				if (sym.st_shndx == SHN_UNDEF)
+					continue;
+
+				if ((name = elf_strptr(e, tabndx,
+				    sym.st_name)) == NULL) {
+					bsdar_warnc(bsdar, 0,
+					    "elf_strptr failed: %s",
+					     elf_errmsg(-1));
+					continue;
+				}
+
+				add_to_ar_sym_table(bsdar, name);
+			}
+		}
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		bsdar_warnc(bsdar, 0, "elf_nextscn failed: %s",
+		     elf_errmsg(elferr));
+}
+
+/*
+ * Append to the archive string table buffer.
+ */
+static void
+add_to_ar_str_table(struct bsdar *bsdar, const char *name)
+{
+
+	if (bsdar->as == NULL) {
+		bsdar->as_cap = _INIT_AS_CAP;
+		bsdar->as_sz = 0;
+		if ((bsdar->as = malloc(bsdar->as_cap)) == NULL)
+			bsdar_errc(bsdar, errno, "malloc failed");
+	}
+
+	/*
+	 * The space required for holding one member name in the 'as'
+	 * table includes: strlen(name) + (1 for '/') + (1 for '\n') +
+	 * (possibly 1 for padding).
+	 */
+	while (bsdar->as_sz + strlen(name) + 3 > bsdar->as_cap) {
+		bsdar->as_cap *= 2;
+		bsdar->as = realloc(bsdar->as, bsdar->as_cap);
+		if (bsdar->as == NULL)
+			bsdar_errc(bsdar, errno, "realloc failed");
+	}
+	strncpy(&bsdar->as[bsdar->as_sz], name, strlen(name));
+	bsdar->as_sz += strlen(name);
+	bsdar->as[bsdar->as_sz++] = '/';
+	bsdar->as[bsdar->as_sz++] = '\n';
+}
+
+/*
+ * Append to the archive symbol table buffer.
+ */
+static void
+add_to_ar_sym_table(struct bsdar *bsdar, const char *name)
+{
+
+	if (bsdar->s_so == NULL) {
+		if ((bsdar->s_so = malloc(_INIT_SYMOFF_CAP)) ==
+		    NULL)
+			bsdar_errc(bsdar, errno, "malloc failed");
+		bsdar->s_so_cap = _INIT_SYMOFF_CAP;
+		bsdar->s_cnt = 0;
+	}
+
+	if (bsdar->s_sn == NULL) {
+		if ((bsdar->s_sn = malloc(_INIT_SYMNAME_CAP)) == NULL)
+			bsdar_errc(bsdar, errno, "malloc failed");
+		bsdar->s_sn_cap = _INIT_SYMNAME_CAP;
+		bsdar->s_sn_sz = 0;
+	}
+
+	if (bsdar->s_cnt * sizeof(uint32_t) >= bsdar->s_so_cap) {
+		bsdar->s_so_cap *= 2;
+		bsdar->s_so = realloc(bsdar->s_so, bsdar->s_so_cap);
+		if (bsdar->s_so == NULL)
+			bsdar_errc(bsdar, errno, "realloc failed");
+	}
+	bsdar->s_so[bsdar->s_cnt] = bsdar->rela_off;
+	bsdar->s_cnt++;
+
+	/*
+	 * The space required for holding one symbol name in the 'sn'
+	 * table includes: strlen(name) + (1 for '\n') + (possibly 1
+	 * for padding).
+	 */
+	while (bsdar->s_sn_sz + strlen(name) + 2 > bsdar->s_sn_cap) {
+		bsdar->s_sn_cap *= 2;
+		bsdar->s_sn = realloc(bsdar->s_sn, bsdar->s_sn_cap);
+		if (bsdar->s_sn == NULL)
+			bsdar_errc(bsdar, errno, "realloc failed");
+	}
+	strncpy(&bsdar->s_sn[bsdar->s_sn_sz], name, strlen(name));
+	bsdar->s_sn_sz += strlen(name);
+	bsdar->s_sn[bsdar->s_sn_sz++] = '\0';
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/brandelf/Makefile	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,9 @@
+# $Id: Makefile 2066 2011-10-26 15:40:28Z jkoshy $
+
+TOP=	..
+
+PROG=	brandelf
+WARNS?=	6
+LDADD=	-lelftc -lelf
+
+.include "${TOP}/mk/elftoolchain.prog.mk"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/brandelf/brandelf.1	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,147 @@
+.\" Copyright 1997 John-Mark Gurney.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
+.\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: src/usr.bin/brandelf/brandelf.1,v 1.17 2007/03/09 14:36:18 ru Exp $
+.\" $Id: brandelf.1 3235 2015-07-31 16:44:47Z emaste $
+.\"
+.Dd October 27, 2014
+.Dt BRANDELF 1
+.Os
+.Sh NAME
+.Nm brandelf
+.Nd mark an ELF binary for a specific ABI
+.Sh SYNOPSIS
+.Nm
+.Op Fl V | Fl -version
+.Op Fl f Ar ELF_ABI_number
+.Op Fl h | Fl -help
+.Op Fl l
+.Op Fl t Ar brand
+.Op Fl v
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility marks an ELF binary to be run under a certain ABI.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl f Ar ELF_ABI_number
+Forces branding with the supplied ELF ABI number.
+Incompatible with the
+.Fl t
+option.
+These values are assigned by SCO/USL.
+.It Fl h | Fl -help
+Print a usage message and exit.
+.It Fl l
+Writes the list of all known ELF types to standard output.
+.It Fl t Ar brand
+Brands the given ELF binaries to be of the ABI specified by argument
+.Ar brand .
+Supported ABIs include
+.Dq Li 86Open ,
+.Dq Li AIX ,
+.Dq Li ARM ,
+.Dq Li AROS ,
+.Dq Li FreeBSD ,
+.Dq Li GNU ,
+.Dq Li HP/UX ,
+.Dq Li Hurd ,
+.Dq Li IRIX ,
+.Dq Li Linux
+(an alias for
+.Dq Li GNU ) ,
+.Dq Li Modesto ,
+.Dq Li NSK ,
+.Dq Li NetBSD ,
+.Dq Li None ,
+.Dq Li OpenBSD ,
+.Dq Li OpenVMS ,
+.Dq Li Standalone ,
+.Dq Li SVR4
+(an alias for
+.Dq Li None ) ,
+.Dq Li Solaris
+and
+.Dq Li Tru64 .
+.It Fl v
+This option is accepted for compatibility with other versions of
+.Nm ,
+but is otherwise ignored.
+.It Fl V | Fl -version
+Print a version identifier and exit.
+.El
+.Pp
+If the options
+.Fl f Ar ELF_ABI_number
+or
+.Fl t Ar brand
+were specified,
+.Nm
+will brand the files named by command-line arguments
+.Ar
+to be of type
+.Ar ELF_ABI_number
+or
+.Ar brand
+respectively.
+.Pp
+If neither of the
+.Fl f
+or
+.Fl t
+options were specified,
+.Nm
+will display the current branding for the files named by the arguments
+.Ar .
+.Sh EXIT STATUS
+Exit status is 0 on success, and 1 if the command
+fails if a file does not exist, is too short, fails to brand properly,
+or the brand requested is not one of the known types and the
+.Fl f
+option is not set.
+.Sh EXAMPLES
+The following is an example of a typical usage
+of the
+.Nm
+command:
+.Bd -literal -offset indent
+brandelf file
+brandelf -t GNU file
+.Ed
+.Sh SEE ALSO
+.Rs
+.%A The Santa Cruz Operation, Inc.
+.%T System V Application Binary Interface
+.%D April 29, 1998 (DRAFT)
+.%O http://www.sco.com/developer/devspecs/
+.Re
+.Sh HISTORY
+The
+.Nm
+manual page first appeared in
+.Fx 2.2 .
+.Sh AUTHORS
+This manual page was written by
+.An John-Mark Gurney Aq Mt jmg@FreeBSD.org .
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/brandelf/brandelf.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,312 @@
+/*-
+ * Copyright (c) 2008 Hyogeol Lee
+ * Copyright (c) 2000, 2001 David O'Brien
+ * Copyright (c) 1996 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <getopt.h>
+#include <libelf.h>
+#include <libelftc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "_elftc.h"
+
+ELFTC_VCSID("$Id: brandelf.c 3440 2016-04-07 14:51:47Z emaste $");
+
+static int elftype(const char *);
+static const char *iselftype(int);
+static void printelftypes(void);
+static void printversion(void);
+static void usage(void);
+
+struct ELFtypes {
+	const char *str;
+	int value;
+};
+/* XXX - any more types? */
+static struct ELFtypes elftypes[] = {
+	{ "86Open",	ELFOSABI_86OPEN },
+	{ "AIX",	ELFOSABI_AIX },
+	{ "ARM",	ELFOSABI_ARM },
+	{ "AROS",	ELFOSABI_AROS },
+	{ "CloudABI",	ELFOSABI_CLOUDABI },
+	{ "FreeBSD",	ELFOSABI_FREEBSD },
+	{ "GNU",	ELFOSABI_GNU },
+	{ "HP/UX",	ELFOSABI_HPUX},
+	{ "Hurd",	ELFOSABI_HURD },
+	{ "IRIX",	ELFOSABI_IRIX },
+	{ "Linux",	ELFOSABI_GNU },
+	{ "Modesto",	ELFOSABI_MODESTO },
+	{ "NSK",	ELFOSABI_NSK },
+	{ "NetBSD",	ELFOSABI_NETBSD},
+	{ "None",	ELFOSABI_NONE},
+	{ "OpenBSD",	ELFOSABI_OPENBSD },
+	{ "OpenVMS",	ELFOSABI_OPENVMS },
+	{ "Standalone",	ELFOSABI_STANDALONE },
+	{ "SVR4",	ELFOSABI_NONE },
+	{ "Solaris",	ELFOSABI_SOLARIS },
+	{ "Tru64",	ELFOSABI_TRU64 }
+};
+
+static struct option brandelf_longopts[] = {
+	{ "help",	no_argument,	NULL,   'h' },
+	{ "version",	no_argument,	NULL, 	'V' },
+	{ NULL,		0,		NULL,	0   }
+};
+
+int
+main(int argc, char **argv)
+{
+	GElf_Ehdr ehdr;
+	Elf *elf;
+	Elf_Kind kind;
+	int type = ELFOSABI_NONE;
+	int retval = 0;
+	int ch, change = 0, force = 0, listed = 0;
+
+	if (elf_version(EV_CURRENT) == EV_NONE)
+		errx(EXIT_FAILURE, "elf_version error");
+
+	while ((ch = getopt_long(argc, argv, "Vf:hlt:v", brandelf_longopts,
+		NULL)) != -1)
+		switch (ch) {
+		case 'f':
+			if (change)
+				errx(EXIT_FAILURE, "ERROR: the -f option is "
+				    "incompatible with the -t option.");
+			force = 1;
+			type = atoi(optarg);
+			if (errno == ERANGE || type < 0 || type > 255) {
+				warnx("ERROR: invalid argument to option "
+				    "-f: %s", optarg);
+				usage();
+			}
+			break;
+		case 'h':
+			usage();
+			break;
+		case 'l':
+			printelftypes();
+			listed = 1;
+			break;
+		case 'v':
+			/* This flag is ignored. */
+			break;
+		case 't':
+			if (force)
+				errx(EXIT_FAILURE, "the -t option is "
+				    "incompatible with the -f option.");
+			if ((type = elftype(optarg)) == -1) {
+				warnx("ERROR: invalid ELF type '%s'", optarg);
+				usage();
+			}
+
+			change = 1;
+			break;
+		case 'V':
+			printversion();
+			break;
+		default:
+			usage();
+	}
+	argc -= optind;
+	argv += optind;
+	if (!argc) {
+		if (listed)
+			exit(0);
+		else {
+			warnx("no file(s) specified");
+			usage();
+		}
+	}
+
+	while (argc) {
+		int fd;
+
+		elf = NULL;
+
+		if ((fd = open(argv[0], (change || force) ? O_RDWR :
+		    O_RDONLY, 0)) < 0) {
+			warn("error opening file %s", argv[0]);
+			retval = 1;
+			goto fail;
+		}
+
+		if ((elf = elf_begin(fd, (change || force) ? ELF_C_RDWR :
+		    ELF_C_READ, NULL)) == NULL) {
+			warnx("elf_begin failed: %s", elf_errmsg(-1));
+			retval = 1;
+			goto fail;
+		}
+
+		if ((kind = elf_kind(elf)) != ELF_K_ELF) {
+			if (kind == ELF_K_AR)
+				warnx("file '%s' is an archive.", argv[0]);
+			else
+				warnx("file '%s' is not an ELF file.",
+				    argv[0]);
+			retval = 1;
+			goto fail;
+		}
+
+		if (gelf_getehdr(elf, &ehdr) == NULL) {
+			warnx("gelf_getehdr: %s", elf_errmsg(-1));
+			retval = 1;
+			goto fail;
+		}
+
+		if (!change && !force) {
+			fprintf(stdout,
+			    "File '%s' is of brand '%s' (%u).\n",
+			    argv[0], iselftype(ehdr.e_ident[EI_OSABI]),
+			    ehdr.e_ident[EI_OSABI]);
+			if (!iselftype(type)) {
+				warnx("ELF ABI Brand '%u' is unknown",
+				      type);
+				printelftypes();
+			}
+		} else {
+
+			/*
+			 * Keep the existing layout of the ELF object.
+			 */
+			if (elf_flagelf(elf, ELF_C_SET, ELF_F_LAYOUT) == 0) {
+				warnx("elf_flagelf failed: %s",
+				    elf_errmsg(-1));
+				retval = 1;
+				goto fail;
+			}
+
+			/*
+			 * Update the ABI type.
+			 */
+			ehdr.e_ident[EI_OSABI] = (unsigned char) type;
+			if (gelf_update_ehdr(elf, &ehdr) == 0) {
+				warnx("gelf_update_ehdr error: %s",
+				    elf_errmsg(-1));
+				retval = 1;
+				goto fail;
+			}
+
+			/*
+			 * Write back changes.
+			 */
+			if (elf_update(elf, ELF_C_WRITE) == -1) {
+				warnx("elf_update error: %s", elf_errmsg(-1));
+				retval = 1;
+				goto fail;
+			}
+		}
+fail:
+
+		if (elf)
+			elf_end(elf);
+
+		if (fd >= 0 && close(fd) == -1) {
+			warnx("%s: close error", argv[0]);
+			retval = 1;
+		}
+
+		argc--;
+		argv++;
+	}
+
+	return (retval);
+}
+
+#define	USAGE_MESSAGE	"\
+Usage: %s [options] file...\n\
+  Set or display the ABI field for an ELF object.\n\n\
+  Supported options are:\n\
+  -f NUM                    Set the ELF ABI to the number 'NUM'.\n\
+  -h | --help               Print a usage message and exit.\n\
+  -l                        List known ELF ABI names.\n\
+  -t ABI                    Set the ELF ABI to the value named by \"ABI\".\n\
+  -V | --version            Print a version identifier and exit.\n"
+
+static void
+usage(void)
+{
+	(void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
+	exit(1);
+}
+
+static void
+printversion(void)
+{
+	(void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version());
+	exit(0);
+}
+
+static const char *
+iselftype(int etype)
+{
+	size_t elfwalk;
+
+	for (elfwalk = 0;
+	     elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
+	     elfwalk++)
+		if (etype == elftypes[elfwalk].value)
+			return (elftypes[elfwalk].str);
+	return (0);
+}
+
+static int
+elftype(const char *elfstrtype)
+{
+	size_t elfwalk;
+
+	for (elfwalk = 0;
+	     elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
+	     elfwalk++)
+		if (strcasecmp(elfstrtype, elftypes[elfwalk].str) == 0)
+			return (elftypes[elfwalk].value);
+	return (-1);
+}
+
+static void
+printelftypes(void)
+{
+	size_t elfwalk;
+
+	(void) printf("Known ELF types are: ");
+	for (elfwalk = 0;
+	     elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
+	     elfwalk++)
+		(void) printf("%s(%u) ", elftypes[elfwalk].str,
+		    elftypes[elfwalk].value);
+	(void) printf("\n");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/common/Makefile	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,18 @@
+# $Id: Makefile 3594 2018-04-11 18:26:50Z jkoshy $
+
+TOP=	..
+
+INCS=		elfdefinitions.h
+INCSDIR=	/usr/include
+
+.PHONY:	all clean clobber depend obj
+
+all depend:
+
+clean clobber:
+	rm -f ${CLEANFILES}
+
+cleandepend:
+	rm -f ${.OBJDIR}/.depend
+
+.include "${TOP}/mk/elftoolchain.inc.mk"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/common/_elftc.h	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,484 @@
+/*-
+ * Copyright (c) 2009 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: _elftc.h 3446 2016-05-03 01:31:17Z emaste $
+ */
+
+/**
+ ** Miscellaneous definitions needed by multiple components.
+ **/
+
+#ifndef	_ELFTC_H
+#define	_ELFTC_H
+
+#ifndef	NULL
+#define NULL 	((void *) 0)
+#endif
+
+#ifndef	offsetof
+#define	offsetof(T, M)		((int) &((T*) 0) -> M)
+#endif
+
+/* --QUEUE-MACROS-- [[ */
+
+/*
+ * Supply macros missing from <sys/queue.h>
+ */
+
+/*
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	LIST_FOREACH_SAFE
+#define	LIST_FOREACH_SAFE(var, head, field, tvar)		\
+	for ((var) = LIST_FIRST((head));			\
+	    (var) && ((tvar) = LIST_NEXT((var), field), 1);	\
+	    (var) = (tvar))
+#endif
+
+#ifndef	SLIST_FOREACH_SAFE
+#define	SLIST_FOREACH_SAFE(var, head, field, tvar)		\
+	for ((var) = SLIST_FIRST((head));			\
+	    (var) && ((tvar) = SLIST_NEXT((var), field), 1);	\
+	    (var) = (tvar))
+#endif
+
+#ifndef	STAILQ_CONCAT
+#define	STAILQ_CONCAT(head1, head2) do {			\
+	if (!STAILQ_EMPTY((head2))) {				\
+		*(head1)->stqh_last = (head2)->stqh_first;	\
+		(head1)->stqh_last = (head2)->stqh_last;	\
+		STAILQ_INIT((head2));				\
+	}							\
+} while (/*CONSTCOND*/0)
+#endif
+
+#ifndef	STAILQ_EMPTY
+#define	STAILQ_EMPTY(head)	((head)->stqh_first == NULL)
+#endif
+
+#ifndef	STAILQ_ENTRY
+#define	STAILQ_ENTRY(type)					\
+struct {							\
+	struct type *stqe_next;	/* next element */		\
+}
+#endif
+
+#ifndef	STAILQ_FIRST
+#define	STAILQ_FIRST(head)	((head)->stqh_first)
+#endif
+
+#ifndef	STAILQ_HEAD
+#define	STAILQ_HEAD(name, type)					\
+struct name {							\
+	struct type *stqh_first; /* first element */		\
+	struct type **stqh_last; /* addr of last next element */ \
+}
+#endif
+
+#ifndef	STAILQ_HEAD_INITIALIZER
+#define	STAILQ_HEAD_INITIALIZER(head)				\
+	{ NULL, &(head).stqh_first }
+#endif
+
+#ifndef	STAILQ_FOREACH
+#define	STAILQ_FOREACH(var, head, field)			\
+	for ((var) = ((head)->stqh_first);			\
+		(var);						\
+		(var) = ((var)->field.stqe_next))
+#endif
+
+#ifndef	STAILQ_FOREACH_SAFE
+#define STAILQ_FOREACH_SAFE(var, head, field, tvar)		\
+       for ((var) = STAILQ_FIRST((head));			\
+	    (var) && ((tvar) = STAILQ_NEXT((var), field), 1);	\
+	    (var) = (tvar))
+#endif
+
+#ifndef	STAILQ_INIT
+#define	STAILQ_INIT(head) do {					\
+	(head)->stqh_first = NULL;				\
+	(head)->stqh_last = &(head)->stqh_first;		\
+} while (/*CONSTCOND*/0)
+#endif
+
+#ifndef	STAILQ_INSERT_HEAD
+#define	STAILQ_INSERT_HEAD(head, elm, field) do {			\
+	if (((elm)->field.stqe_next = (head)->stqh_first) == NULL)	\
+		(head)->stqh_last = &(elm)->field.stqe_next;		\
+	(head)->stqh_first = (elm);					\
+} while (/*CONSTCOND*/0)
+#endif
+
+#ifndef	STAILQ_INSERT_TAIL
+#define	STAILQ_INSERT_TAIL(head, elm, field) do {			\
+	(elm)->field.stqe_next = NULL;					\
+	*(head)->stqh_last = (elm);					\
+	(head)->stqh_last = &(elm)->field.stqe_next;			\
+} while (/*CONSTCOND*/0)
+#endif
+
+#ifndef	STAILQ_INSERT_AFTER
+#define	STAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\
+		(head)->stqh_last = &(elm)->field.stqe_next;		\
+	(listelm)->field.stqe_next = (elm);				\
+} while (/*CONSTCOND*/0)
+#endif
+
+#ifndef	STAILQ_LAST
+#define STAILQ_LAST(head, type, field)					\
+	(STAILQ_EMPTY((head)) ?					\
+	    NULL : ((struct type *)(void *)				\
+	    ((char *)((head)->stqh_last) - offsetof(struct type, field))))
+#endif
+
+#ifndef	STAILQ_NEXT
+#define	STAILQ_NEXT(elm, field)	((elm)->field.stqe_next)
+#endif
+
+#ifndef	STAILQ_REMOVE
+#define	STAILQ_REMOVE(head, elm, type, field) do {			\
+	if ((head)->stqh_first == (elm)) {				\
+		STAILQ_REMOVE_HEAD((head), field);			\
+	} else {							\
+		struct type *curelm = (head)->stqh_first;		\
+		while (curelm->field.stqe_next != (elm))		\
+			curelm = curelm->field.stqe_next;		\
+		if ((curelm->field.stqe_next =				\
+			curelm->field.stqe_next->field.stqe_next) == NULL) \
+			    (head)->stqh_last = &(curelm)->field.stqe_next; \
+	}								\
+} while (/*CONSTCOND*/0)
+#endif
+
+#ifndef	STAILQ_REMOVE_HEAD
+#define	STAILQ_REMOVE_HEAD(head, field) do {				\
+	if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == \
+	    NULL)							\
+		(head)->stqh_last = &(head)->stqh_first;		\
+} while (/*CONSTCOND*/0)
+#endif
+
+/*
+ * The STAILQ_SORT macro is adapted from Simon Tatham's O(n*log(n))
+ * mergesort algorithm.
+ */
+#ifndef	STAILQ_SORT
+#define	STAILQ_SORT(head, type, field, cmp) do {			\
+	STAILQ_HEAD(, type) _la, _lb;					\
+	struct type *_p, *_q, *_e;					\
+	int _i, _sz, _nmerges, _psz, _qsz;				\
+									\
+	_sz = 1;							\
+	do {								\
+		_nmerges = 0;						\
+		STAILQ_INIT(&_lb);					\
+		while (!STAILQ_EMPTY((head))) {				\
+			_nmerges++;					\
+			STAILQ_INIT(&_la);				\
+			_psz = 0;					\
+			for (_i = 0; _i < _sz && !STAILQ_EMPTY((head));	\
+			     _i++) {					\
+				_e = STAILQ_FIRST((head));		\
+				if (_e == NULL)				\
+					break;				\
+				_psz++;					\
+				STAILQ_REMOVE_HEAD((head), field);	\
+				STAILQ_INSERT_TAIL(&_la, _e, field);	\
+			}						\
+			_p = STAILQ_FIRST(&_la);			\
+			_qsz = _sz;					\
+			_q = STAILQ_FIRST((head));			\
+			while (_psz > 0 || (_qsz > 0 && _q != NULL)) {	\
+				if (_psz == 0) {			\
+					_e = _q;			\
+					_q = STAILQ_NEXT(_q, field);	\
+					STAILQ_REMOVE_HEAD((head),	\
+					    field);			\
+					_qsz--;				\
+				} else if (_qsz == 0 || _q == NULL) {	\
+					_e = _p;			\
+					_p = STAILQ_NEXT(_p, field);	\
+					STAILQ_REMOVE_HEAD(&_la, field);\
+					_psz--;				\
+				} else if (cmp(_p, _q) <= 0) {		\
+					_e = _p;			\
+					_p = STAILQ_NEXT(_p, field);	\
+					STAILQ_REMOVE_HEAD(&_la, field);\
+					_psz--;				\
+				} else {				\
+					_e = _q;			\
+					_q = STAILQ_NEXT(_q, field);	\
+					STAILQ_REMOVE_HEAD((head),	\
+					    field);			\
+					_qsz--;				\
+				}					\
+				STAILQ_INSERT_TAIL(&_lb, _e, field);	\
+			}						\
+		}							\
+		(head)->stqh_first = _lb.stqh_first;			\
+		(head)->stqh_last = _lb.stqh_last;			\
+		_sz *= 2;						\
+	} while (_nmerges > 1);						\
+} while (/*CONSTCOND*/0)
+#endif
+
+#ifndef	TAILQ_FOREACH_SAFE
+#define TAILQ_FOREACH_SAFE(var, head, field, tvar)                      \
+	for ((var) = TAILQ_FIRST((head));                               \
+	    (var) && ((tvar) = TAILQ_NEXT((var), field), 1);            \
+	    (var) = (tvar))
+#endif
+
+/* ]] --QUEUE-MACROS-- */
+
+/*
+ * VCS Ids.
+ */
+
+#ifndef	ELFTC_VCSID
+
+#if defined(__DragonFly__)
+#define	ELFTC_VCSID(ID)		__RCSID(ID)
+#endif
+
+#if defined(__FreeBSD__)
+#define	ELFTC_VCSID(ID)		__FBSDID(ID)
+#endif
+
+#if defined(__APPLE__) || defined(__GLIBC__) || defined(__GNU__) || \
+    defined(__linux__)
+#if defined(__GNUC__)
+#define	ELFTC_VCSID(ID)		__asm__(".ident\t\"" ID "\"")
+#else
+#define	ELFTC_VCSID(ID)		/**/
+#endif
+#endif
+
+#if defined(__minix)
+#if defined(__GNUC__)
+#define	ELFTC_VCSID(ID)		__asm__(".ident\t\"" ID "\"")
+#else
+#define	ELFTC_VCSID(ID)		/**/
+#endif	/* __GNU__ */
+#endif
+
+#if defined(__NetBSD__)
+#define	ELFTC_VCSID(ID)		__RCSID(ID)
+#endif
+
+#if defined(__OpenBSD__)
+#if defined(__GNUC__)
+#define	ELFTC_VCSID(ID)		__asm__(".ident\t\"" ID "\"")
+#else
+#define	ELFTC_VCSID(ID)		/**/
+#endif	/* __GNUC__ */
+#endif
+
+#endif	/* ELFTC_VCSID */
+
+/*
+ * Provide an equivalent for getprogname(3).
+ */
+
+#ifndef	ELFTC_GETPROGNAME
+
+#if defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || \
+    defined(__minix) || defined(__NetBSD__)
+
+#include <stdlib.h>
+
+#define	ELFTC_GETPROGNAME()	getprogname()
+
+#endif	/* __DragonFly__ || __FreeBSD__ || __minix || __NetBSD__ */
+
+
+#if defined(__GLIBC__) || defined(__linux__)
+#ifndef _GNU_SOURCE
+/*
+ * GLIBC based systems have a global 'char *' pointer referencing
+ * the executable's name.
+ */
+extern const char *program_invocation_short_name;
+#endif	/* !_GNU_SOURCE */
+
+#define	ELFTC_GETPROGNAME()	program_invocation_short_name
+
+#endif	/* __GLIBC__ || __linux__ */
+
+
+#if defined(__OpenBSD__)
+
+extern const char *__progname;
+
+#define	ELFTC_GETPROGNAME()	__progname
+
+#endif	/* __OpenBSD__ */
+
+#endif	/* ELFTC_GETPROGNAME */
+
+
+/**
+ ** Per-OS configuration.
+ **/
+
+#if defined(__APPLE__)
+
+#include <libkern/OSByteOrder.h>
+#define	htobe32(x)	OSSwapHostToBigInt32(x)
+#define	roundup2	roundup
+
+#define	ELFTC_BYTE_ORDER			_BYTE_ORDER
+#define	ELFTC_BYTE_ORDER_LITTLE_ENDIAN		_LITTLE_ENDIAN
+#define	ELFTC_BYTE_ORDER_BIG_ENDIAN		_BIG_ENDIAN
+
+#define	ELFTC_HAVE_MMAP				1
+#define	ELFTC_HAVE_STRMODE			1
+
+#define ELFTC_NEED_BYTEORDER_EXTENSIONS		1
+#endif /* __APPLE__ */
+
+
+#if defined(__DragonFly__)
+
+#include <osreldate.h>
+#include <sys/endian.h>
+
+#define	ELFTC_BYTE_ORDER			_BYTE_ORDER
+#define	ELFTC_BYTE_ORDER_LITTLE_ENDIAN		_LITTLE_ENDIAN
+#define	ELFTC_BYTE_ORDER_BIG_ENDIAN		_BIG_ENDIAN
+
+#define	ELFTC_HAVE_MMAP				1
+
+#endif
+
+#if defined(__GLIBC__) || defined(__linux__)
+
+#include <endian.h>
+
+#define	ELFTC_BYTE_ORDER			__BYTE_ORDER
+#define	ELFTC_BYTE_ORDER_LITTLE_ENDIAN		__LITTLE_ENDIAN
+#define	ELFTC_BYTE_ORDER_BIG_ENDIAN		__BIG_ENDIAN
+
+#define	ELFTC_HAVE_MMAP				1
+
+/*
+ * Debian GNU/Linux and Debian GNU/kFreeBSD do not have strmode(3).
+ */
+#define	ELFTC_HAVE_STRMODE			0
+
+/* Whether we need to supply {be,le}32dec. */
+#define ELFTC_NEED_BYTEORDER_EXTENSIONS		1
+
+#define	roundup2	roundup
+
+#endif	/* __GLIBC__ || __linux__ */
+
+
+#if defined(__FreeBSD__)
+
+#include <osreldate.h>
+#include <sys/endian.h>
+
+#define	ELFTC_BYTE_ORDER			_BYTE_ORDER
+#define	ELFTC_BYTE_ORDER_LITTLE_ENDIAN		_LITTLE_ENDIAN
+#define	ELFTC_BYTE_ORDER_BIG_ENDIAN		_BIG_ENDIAN
+
+#define	ELFTC_HAVE_MMAP				1
+#define	ELFTC_HAVE_STRMODE			1
+#if __FreeBSD_version <= 900000
+#define	ELFTC_BROKEN_YY_NO_INPUT		1
+#endif
+#endif	/* __FreeBSD__ */
+
+
+#if defined(__minix)
+#define	ELFTC_HAVE_MMAP				0
+#endif	/* __minix */
+
+
+#if defined(__NetBSD__)
+
+#include <sys/param.h>
+#include <sys/endian.h>
+
+#define	ELFTC_BYTE_ORDER			_BYTE_ORDER
+#define	ELFTC_BYTE_ORDER_LITTLE_ENDIAN		_LITTLE_ENDIAN
+#define	ELFTC_BYTE_ORDER_BIG_ENDIAN		_BIG_ENDIAN
+
+#define	ELFTC_HAVE_MMAP				1
+#define	ELFTC_HAVE_STRMODE			1
+#if __NetBSD_Version__ <= 599002100
+/* from src/doc/CHANGES: flex(1): Import flex-2.5.35 [christos 20091025] */
+/* and 5.99.21 was from Wed Oct 21 21:28:36 2009 UTC */
+#  define ELFTC_BROKEN_YY_NO_INPUT		1
+#endif
+#endif	/* __NetBSD __ */
+
+
+#if defined(__OpenBSD__)
+
+#include <sys/param.h>
+#include <sys/endian.h>
+
+#define	ELFTC_BYTE_ORDER			_BYTE_ORDER
+#define	ELFTC_BYTE_ORDER_LITTLE_ENDIAN		_LITTLE_ENDIAN
+#define	ELFTC_BYTE_ORDER_BIG_ENDIAN		_BIG_ENDIAN
+
+#define	ELFTC_HAVE_MMAP				1
+#define	ELFTC_HAVE_STRMODE			1
+
+#define	ELFTC_NEED_BYTEORDER_EXTENSIONS		1
+#define	roundup2	roundup
+
+#endif	/* __OpenBSD__ */
+
+#endif	/* _ELFTC_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/common/elfdefinitions.h	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,2900 @@
+/*-
+ * Copyright (c) 2010 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: elfdefinitions.h 3515 2017-01-24 22:04:22Z emaste $
+ */
+
+/*
+ * These definitions are based on:
+ * - The public specification of the ELF format as defined in the
+ *   October 2009 draft of System V ABI.
+ *   See: http://www.sco.com/developers/gabi/latest/ch4.intro.html
+ * - The May 1998 (version 1.5) draft of "The ELF-64 object format".
+ * - Processor-specific ELF ABI definitions for sparc, i386, amd64, mips,
+ *   ia64, and powerpc processors.
+ * - The "Linkers and Libraries Guide", from Sun Microsystems.
+ */
+
+#ifndef _ELFDEFINITIONS_H_
+#define _ELFDEFINITIONS_H_
+
+#include <stdint.h>
+
+/*
+ * Types of capabilities.
+ */
+
+#define	_ELF_DEFINE_CAPABILITIES()				\
+_ELF_DEFINE_CA(CA_SUNW_NULL,	0,	"ignored")		\
+_ELF_DEFINE_CA(CA_SUNW_HW_1,	1,	"hardware capability")	\
+_ELF_DEFINE_CA(CA_SUNW_SW_1,	2,	"software capability")
+
+#undef	_ELF_DEFINE_CA
+#define	_ELF_DEFINE_CA(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_CAPABILITIES()
+	CA__LAST__
+};
+
+/*
+ * Flags used with dynamic linking entries.
+ */
+
+#define	_ELF_DEFINE_DYN_FLAGS()					\
+_ELF_DEFINE_DF(DF_ORIGIN,           0x1,			\
+	"object being loaded may refer to $ORIGIN")		\
+_ELF_DEFINE_DF(DF_SYMBOLIC,         0x2,			\
+	"search library for references before executable")	\
+_ELF_DEFINE_DF(DF_TEXTREL,          0x4,			\
+	"relocation entries may modify text segment")		\
+_ELF_DEFINE_DF(DF_BIND_NOW,         0x8,			\
+	"process relocation entries at load time")		\
+_ELF_DEFINE_DF(DF_STATIC_TLS,       0x10,			\
+	"uses static thread-local storage")
+#undef	_ELF_DEFINE_DF
+#define	_ELF_DEFINE_DF(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_DYN_FLAGS()
+	DF__LAST__
+};
+
+
+/*
+ * Dynamic linking entry types.
+ */
+
+#define	_ELF_DEFINE_DYN_TYPES()						\
+_ELF_DEFINE_DT(DT_NULL,             0, "end of array")			\
+_ELF_DEFINE_DT(DT_NEEDED,           1, "names a needed library")	\
+_ELF_DEFINE_DT(DT_PLTRELSZ,         2,					\
+	"size in bytes of associated relocation entries")		\
+_ELF_DEFINE_DT(DT_PLTGOT,           3,					\
+	"address associated with the procedure linkage table")		\
+_ELF_DEFINE_DT(DT_HASH,             4,					\
+	"address of the symbol hash table")				\
+_ELF_DEFINE_DT(DT_STRTAB,           5,					\
+	"address of the string table")					\
+_ELF_DEFINE_DT(DT_SYMTAB,           6,					\
+	"address of the symbol table")					\
+_ELF_DEFINE_DT(DT_RELA,             7,					\
+	"address of the relocation table")				\
+_ELF_DEFINE_DT(DT_RELASZ,           8, "size of the DT_RELA table")	\
+_ELF_DEFINE_DT(DT_RELAENT,          9, "size of each DT_RELA entry")	\
+_ELF_DEFINE_DT(DT_STRSZ,            10, "size of the string table")	\
+_ELF_DEFINE_DT(DT_SYMENT,           11,					\
+	"size of a symbol table entry")					\
+_ELF_DEFINE_DT(DT_INIT,             12,					\
+	"address of the initialization function")			\
+_ELF_DEFINE_DT(DT_FINI,             13,					\
+	"address of the finalization function")				\
+_ELF_DEFINE_DT(DT_SONAME,           14, "names the shared object")	\
+_ELF_DEFINE_DT(DT_RPATH,            15,					\
+	"runtime library search path")					\
+_ELF_DEFINE_DT(DT_SYMBOLIC,         16,					\
+	"alter symbol resolution algorithm")				\
+_ELF_DEFINE_DT(DT_REL,              17,					\
+	"address of the DT_REL table")					\
+_ELF_DEFINE_DT(DT_RELSZ,            18, "size of the DT_REL table")	\
+_ELF_DEFINE_DT(DT_RELENT,           19, "size of each DT_REL entry")	\
+_ELF_DEFINE_DT(DT_PLTREL,           20,					\
+	"type of relocation entry in the procedure linkage table")	\
+_ELF_DEFINE_DT(DT_DEBUG,            21, "used for debugging")		\
+_ELF_DEFINE_DT(DT_TEXTREL,          22,					\
+	"text segment may be written to during relocation")		\
+_ELF_DEFINE_DT(DT_JMPREL,           23,					\
+	"address of relocation entries associated with the procedure linkage table") \
+_ELF_DEFINE_DT(DT_BIND_NOW,         24,					\
+	"bind symbols at loading time")					\
+_ELF_DEFINE_DT(DT_INIT_ARRAY,       25,					\
+	"pointers to initialization functions")				\
+_ELF_DEFINE_DT(DT_FINI_ARRAY,       26,					\
+	"pointers to termination functions")				\
+_ELF_DEFINE_DT(DT_INIT_ARRAYSZ,     27, "size of the DT_INIT_ARRAY")	\
+_ELF_DEFINE_DT(DT_FINI_ARRAYSZ,     28, "size of the DT_FINI_ARRAY")	\
+_ELF_DEFINE_DT(DT_RUNPATH,          29,					\
+	"index of library search path string")				\
+_ELF_DEFINE_DT(DT_FLAGS,            30,					\
+	"flags specific to the object being loaded")			\
+_ELF_DEFINE_DT(DT_ENCODING,         32, "standard semantics")		\
+_ELF_DEFINE_DT(DT_PREINIT_ARRAY,    32,					\
+	"pointers to pre-initialization functions")			\
+_ELF_DEFINE_DT(DT_PREINIT_ARRAYSZ,  33,					\
+	"size of pre-initialization array")				\
+_ELF_DEFINE_DT(DT_MAXPOSTAGS,	    34,					\
+	"the number of positive tags")					\
+_ELF_DEFINE_DT(DT_LOOS,             0x6000000DUL,			\
+	"start of OS-specific types")					\
+_ELF_DEFINE_DT(DT_SUNW_AUXILIARY,   0x6000000DUL,			\
+	"offset of string naming auxiliary filtees")			\
+_ELF_DEFINE_DT(DT_SUNW_RTLDINF,     0x6000000EUL, "rtld internal use")	\
+_ELF_DEFINE_DT(DT_SUNW_FILTER,      0x6000000FUL,			\
+	"offset of string naming standard filtees")			\
+_ELF_DEFINE_DT(DT_SUNW_CAP,         0x60000010UL,			\
+	"address of hardware capabilities section")			\
+_ELF_DEFINE_DT(DT_SUNW_ASLR,        0x60000023UL,			\
+	"Address Space Layout Randomization flag")			\
+_ELF_DEFINE_DT(DT_HIOS,             0x6FFFF000UL,			\
+	"end of OS-specific types")					\
+_ELF_DEFINE_DT(DT_VALRNGLO,         0x6FFFFD00UL,			\
+	"start of range using the d_val field")				\
+_ELF_DEFINE_DT(DT_GNU_PRELINKED,    0x6FFFFDF5UL,			\
+	"prelinking timestamp")						\
+_ELF_DEFINE_DT(DT_GNU_CONFLICTSZ,   0x6FFFFDF6UL,			\
+	"size of conflict section")					\
+_ELF_DEFINE_DT(DT_GNU_LIBLISTSZ,    0x6FFFFDF7UL,			\
+	"size of library list")						\
+_ELF_DEFINE_DT(DT_CHECKSUM,         0x6FFFFDF8UL,			\
+	"checksum for the object")					\
+_ELF_DEFINE_DT(DT_PLTPADSZ,         0x6FFFFDF9UL,			\
+	"size of PLT padding")						\
+_ELF_DEFINE_DT(DT_MOVEENT,          0x6FFFFDFAUL,			\
+	"size of DT_MOVETAB entries")					\
+_ELF_DEFINE_DT(DT_MOVESZ,           0x6FFFFDFBUL,			\
+	"total size of the MOVETAB table")				\
+_ELF_DEFINE_DT(DT_FEATURE,          0x6FFFFDFCUL, "feature values")	\
+_ELF_DEFINE_DT(DT_POSFLAG_1,        0x6FFFFDFDUL,			\
+	"dynamic position flags")					\
+_ELF_DEFINE_DT(DT_SYMINSZ,          0x6FFFFDFEUL,			\
+	"size of the DT_SYMINFO table")					\
+_ELF_DEFINE_DT(DT_SYMINENT,         0x6FFFFDFFUL,			\
+	"size of a DT_SYMINFO entry")					\
+_ELF_DEFINE_DT(DT_VALRNGHI,         0x6FFFFDFFUL,			\
+	"end of range using the d_val field")				\
+_ELF_DEFINE_DT(DT_ADDRRNGLO,        0x6FFFFE00UL,			\
+	"start of range using the d_ptr field")				\
+_ELF_DEFINE_DT(DT_GNU_HASH,	    0x6FFFFEF5UL,			\
+	"GNU style hash tables")					\
+_ELF_DEFINE_DT(DT_TLSDESC_PLT,	    0x6FFFFEF6UL,			\
+	"location of PLT entry for TLS descriptor resolver calls")	\
+_ELF_DEFINE_DT(DT_TLSDESC_GOT,	    0x6FFFFEF7UL,			\
+	"location of GOT entry used by TLS descriptor resolver PLT entry") \
+_ELF_DEFINE_DT(DT_GNU_CONFLICT,     0x6FFFFEF8UL,			\
+	"address of conflict section")					\
+_ELF_DEFINE_DT(DT_GNU_LIBLIST,      0x6FFFFEF9UL,			\
+	"address of conflict section")					\
+_ELF_DEFINE_DT(DT_CONFIG,           0x6FFFFEFAUL,			\
+	"configuration file")						\
+_ELF_DEFINE_DT(DT_DEPAUDIT,         0x6FFFFEFBUL,			\
+	"string defining audit libraries")				\
+_ELF_DEFINE_DT(DT_AUDIT,            0x6FFFFEFCUL,			\
+	"string defining audit libraries")				\
+_ELF_DEFINE_DT(DT_PLTPAD,           0x6FFFFEFDUL, "PLT padding")	\
+_ELF_DEFINE_DT(DT_MOVETAB,          0x6FFFFEFEUL,			\
+	"address of a move table")					\
+_ELF_DEFINE_DT(DT_SYMINFO,          0x6FFFFEFFUL,			\
+	"address of the symbol information table")			\
+_ELF_DEFINE_DT(DT_ADDRRNGHI,        0x6FFFFEFFUL,			\
+	"end of range using the d_ptr field")				\
+_ELF_DEFINE_DT(DT_VERSYM,	    0x6FFFFFF0UL,			\
+	"address of the version section")				\
+_ELF_DEFINE_DT(DT_RELACOUNT,        0x6FFFFFF9UL,			\
+	"count of RELA relocations")					\
+_ELF_DEFINE_DT(DT_RELCOUNT,         0x6FFFFFFAUL,			\
+	"count of REL relocations")					\
+_ELF_DEFINE_DT(DT_FLAGS_1,          0x6FFFFFFBUL, "flag values")	\
+_ELF_DEFINE_DT(DT_VERDEF,	    0x6FFFFFFCUL,			\
+	"address of the version definition segment")			\
+_ELF_DEFINE_DT(DT_VERDEFNUM,	    0x6FFFFFFDUL,			\
+	"the number of version definition entries")			\
+_ELF_DEFINE_DT(DT_VERNEED,	    0x6FFFFFFEUL,			\
+	"address of section with needed versions")			\
+_ELF_DEFINE_DT(DT_VERNEEDNUM,       0x6FFFFFFFUL,			\
+	"the number of version needed entries")				\
+_ELF_DEFINE_DT(DT_LOPROC,           0x70000000UL,			\
+	"start of processor-specific types")				\
+_ELF_DEFINE_DT(DT_ARM_SYMTABSZ,	    0x70000001UL,			\
+	"number of entries in the dynamic symbol table")		\
+_ELF_DEFINE_DT(DT_SPARC_REGISTER,   0x70000001UL,			\
+	"index of an STT_SPARC_REGISTER symbol")			\
+_ELF_DEFINE_DT(DT_ARM_PREEMPTMAP,   0x70000002UL,			\
+	"address of the preemption map")				\
+_ELF_DEFINE_DT(DT_MIPS_RLD_VERSION, 0x70000001UL,			\
+	"version ID for runtime linker interface")			\
+_ELF_DEFINE_DT(DT_MIPS_TIME_STAMP,  0x70000002UL,			\
+	"timestamp")							\
+_ELF_DEFINE_DT(DT_MIPS_ICHECKSUM,   0x70000003UL,			\
+	"checksum of all external strings and common sizes")		\
+_ELF_DEFINE_DT(DT_MIPS_IVERSION,    0x70000004UL,			\
+	"string table index of a version string")			\
+_ELF_DEFINE_DT(DT_MIPS_FLAGS,       0x70000005UL,			\
+	"MIPS-specific flags")						\
+_ELF_DEFINE_DT(DT_MIPS_BASE_ADDRESS, 0x70000006UL,			\
+	"base address for the executable/DSO")				\
+_ELF_DEFINE_DT(DT_MIPS_CONFLICT,    0x70000008UL,			\
+	"address of .conflict section")					\
+_ELF_DEFINE_DT(DT_MIPS_LIBLIST,     0x70000009UL,			\
+	"address of .liblist section")					\
+_ELF_DEFINE_DT(DT_MIPS_LOCAL_GOTNO, 0x7000000AUL,			\
+	"number of local GOT entries")					\
+_ELF_DEFINE_DT(DT_MIPS_CONFLICTNO,  0x7000000BUL,			\
+	"number of entries in the .conflict section")			\
+_ELF_DEFINE_DT(DT_MIPS_LIBLISTNO,   0x70000010UL,			\
+	"number of entries in the .liblist section")			\
+_ELF_DEFINE_DT(DT_MIPS_SYMTABNO,    0x70000011UL,			\
+	"number of entries in the .dynsym section")			\
+_ELF_DEFINE_DT(DT_MIPS_UNREFEXTNO,  0x70000012UL,			\
+	"index of first external dynamic symbol not ref'ed locally")	\
+_ELF_DEFINE_DT(DT_MIPS_GOTSYM,      0x70000013UL,			\
+	"index of first dynamic symbol corresponds to a GOT entry")	\
+_ELF_DEFINE_DT(DT_MIPS_HIPAGENO,    0x70000014UL,			\
+	"number of page table entries in GOT")				\
+_ELF_DEFINE_DT(DT_MIPS_RLD_MAP,     0x70000016UL,			\
+	"address of runtime linker map")				\
+_ELF_DEFINE_DT(DT_MIPS_DELTA_CLASS, 0x70000017UL,			\
+	"Delta C++ class definition")					\
+_ELF_DEFINE_DT(DT_MIPS_DELTA_CLASS_NO, 0x70000018UL,			\
+	"number of entries in DT_MIPS_DELTA_CLASS")			\
+_ELF_DEFINE_DT(DT_MIPS_DELTA_INSTANCE, 0x70000019UL,			\
+	"Delta C++ class instances")					\
+_ELF_DEFINE_DT(DT_MIPS_DELTA_INSTANCE_NO, 0x7000001AUL,			\
+	"number of entries in DT_MIPS_DELTA_INSTANCE")			\
+_ELF_DEFINE_DT(DT_MIPS_DELTA_RELOC, 0x7000001BUL,			\
+	"Delta relocations")						\
+_ELF_DEFINE_DT(DT_MIPS_DELTA_RELOC_NO, 0x7000001CUL,			\
+	"number of entries in DT_MIPS_DELTA_RELOC")			\
+_ELF_DEFINE_DT(DT_MIPS_DELTA_SYM,   0x7000001DUL,			\
+	"Delta symbols referred by Delta relocations")			\
+_ELF_DEFINE_DT(DT_MIPS_DELTA_SYM_NO, 0x7000001EUL,			\
+	"number of entries in DT_MIPS_DELTA_SYM")			\
+_ELF_DEFINE_DT(DT_MIPS_DELTA_CLASSSYM, 0x70000020UL,			\
+	"Delta symbols for class declarations")				\
+_ELF_DEFINE_DT(DT_MIPS_DELTA_CLASSSYM_NO, 0x70000021UL,			\
+	"number of entries in DT_MIPS_DELTA_CLASSSYM")			\
+_ELF_DEFINE_DT(DT_MIPS_CXX_FLAGS,   0x70000022UL,			\
+	"C++ flavor flags")						\
+_ELF_DEFINE_DT(DT_MIPS_PIXIE_INIT,  0x70000023UL,			\
+	"address of an initialization routine created by pixie")	\
+_ELF_DEFINE_DT(DT_MIPS_SYMBOL_LIB,  0x70000024UL,			\
+	"address of .MIPS.symlib section")				\
+_ELF_DEFINE_DT(DT_MIPS_LOCALPAGE_GOTIDX, 0x70000025UL,			\
+	"GOT index of first page table entry for a segment")		\
+_ELF_DEFINE_DT(DT_MIPS_LOCAL_GOTIDX, 0x70000026UL,			\
+	"GOT index of first page table entry for a local symbol")	\
+_ELF_DEFINE_DT(DT_MIPS_HIDDEN_GOTIDX, 0x70000027UL,			\
+	"GOT index of first page table entry for a hidden symbol")	\
+_ELF_DEFINE_DT(DT_MIPS_PROTECTED_GOTIDX, 0x70000028UL,			\
+	"GOT index of first page table entry for a protected symbol")	\
+_ELF_DEFINE_DT(DT_MIPS_OPTIONS,     0x70000029UL,			\
+	"address of .MIPS.options section")				\
+_ELF_DEFINE_DT(DT_MIPS_INTERFACE,   0x7000002AUL,			\
+	"address of .MIPS.interface section")				\
+_ELF_DEFINE_DT(DT_MIPS_DYNSTR_ALIGN, 0x7000002BUL, "???")		\
+_ELF_DEFINE_DT(DT_MIPS_INTERFACE_SIZE, 0x7000002CUL,			\
+	"size of .MIPS.interface section")				\
+_ELF_DEFINE_DT(DT_MIPS_RLD_TEXT_RESOLVE_ADDR, 0x7000002DUL,		\
+	"address of _rld_text_resolve in GOT")				\
+_ELF_DEFINE_DT(DT_MIPS_PERF_SUFFIX, 0x7000002EUL,			\
+	"default suffix of DSO to be appended by dlopen")		\
+_ELF_DEFINE_DT(DT_MIPS_COMPACT_SIZE, 0x7000002FUL,			\
+	"size of a ucode compact relocation record (o32)")		\
+_ELF_DEFINE_DT(DT_MIPS_GP_VALUE,    0x70000030UL,			\
+	"GP value of a specified GP relative range")			\
+_ELF_DEFINE_DT(DT_MIPS_AUX_DYNAMIC, 0x70000031UL,			\
+	"address of an auxiliary dynamic table")			\
+_ELF_DEFINE_DT(DT_MIPS_PLTGOT,      0x70000032UL,			\
+	"address of the PLTGOT")					\
+_ELF_DEFINE_DT(DT_MIPS_RLD_OBJ_UPDATE, 0x70000033UL,			\
+	"object list update callback")					\
+_ELF_DEFINE_DT(DT_MIPS_RWPLT,       0x70000034UL,			\
+	"address of a writable PLT")					\
+_ELF_DEFINE_DT(DT_PPC_GOT,          0x70000000UL,			\
+	"value of _GLOBAL_OFFSET_TABLE_")				\
+_ELF_DEFINE_DT(DT_PPC_TLSOPT,       0x70000001UL,			\
+	"TLS descriptor should be optimized")				\
+_ELF_DEFINE_DT(DT_PPC64_GLINK,      0x70000000UL,			\
+	"address of .glink section")					\
+_ELF_DEFINE_DT(DT_PPC64_OPD,        0x70000001UL,			\
+	"address of .opd section")					\
+_ELF_DEFINE_DT(DT_PPC64_OPDSZ,      0x70000002UL,			\
+	"size of .opd section")						\
+_ELF_DEFINE_DT(DT_PPC64_TLSOPT,     0x70000003UL,			\
+	"TLS descriptor should be optimized")				\
+_ELF_DEFINE_DT(DT_AUXILIARY,        0x7FFFFFFDUL,			\
+	"offset of string naming auxiliary filtees")			\
+_ELF_DEFINE_DT(DT_USED,             0x7FFFFFFEUL, "ignored")		\
+_ELF_DEFINE_DT(DT_FILTER,           0x7FFFFFFFUL,			\
+	"index of string naming filtees")				\
+_ELF_DEFINE_DT(DT_HIPROC,           0x7FFFFFFFUL,			\
+	"end of processor-specific types")
+
+#undef	_ELF_DEFINE_DT
+#define	_ELF_DEFINE_DT(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_DYN_TYPES()
+	DT__LAST__ = DT_HIPROC
+};
+
+#define	DT_DEPRECATED_SPARC_REGISTER	DT_SPARC_REGISTER
+
+/*
+ * Flags used in the executable header (field: e_flags).
+ */
+#define	_ELF_DEFINE_EHDR_FLAGS()					\
+_ELF_DEFINE_EF(EF_ARM_RELEXEC,      0x00000001UL,			\
+	"dynamic segment describes only how to relocate segments")	\
+_ELF_DEFINE_EF(EF_ARM_HASENTRY,     0x00000002UL,			\
+	"e_entry contains a program entry point")			\
+_ELF_DEFINE_EF(EF_ARM_SYMSARESORTED, 0x00000004UL,			\
+	"subsection of symbol table is sorted by symbol value")		\
+_ELF_DEFINE_EF(EF_ARM_DYNSYMSUSESEGIDX, 0x00000008UL,			\
+	"dynamic symbol st_shndx = containing segment index + 1")	\
+_ELF_DEFINE_EF(EF_ARM_MAPSYMSFIRST, 0x00000010UL,			\
+	"mapping symbols precede other local symbols in symtab")	\
+_ELF_DEFINE_EF(EF_ARM_BE8,          0x00800000UL,			\
+	"file contains BE-8 code")					\
+_ELF_DEFINE_EF(EF_ARM_LE8,          0x00400000UL,			\
+	"file contains LE-8 code")					\
+_ELF_DEFINE_EF(EF_ARM_EABIMASK,     0xFF000000UL,			\
+	"mask for ARM EABI version number (0 denotes GNU or unknown)")	\
+_ELF_DEFINE_EF(EF_ARM_EABI_UNKNOWN, 0x00000000UL,			\
+	"Unknown or GNU ARM EABI version number")			\
+_ELF_DEFINE_EF(EF_ARM_EABI_VER1,    0x01000000UL,			\
+	"ARM EABI version 1")						\
+_ELF_DEFINE_EF(EF_ARM_EABI_VER2,    0x02000000UL,			\
+	"ARM EABI version 2")						\
+_ELF_DEFINE_EF(EF_ARM_EABI_VER3,    0x03000000UL,			\
+	"ARM EABI version 3")						\
+_ELF_DEFINE_EF(EF_ARM_EABI_VER4,    0x04000000UL,			\
+	"ARM EABI version 4")						\
+_ELF_DEFINE_EF(EF_ARM_EABI_VER5,    0x05000000UL,			\
+	"ARM EABI version 5")						\
+_ELF_DEFINE_EF(EF_ARM_INTERWORK,    0x00000004UL,			\
+	"GNU EABI extension")						\
+_ELF_DEFINE_EF(EF_ARM_APCS_26,      0x00000008UL,			\
+	"GNU EABI extension")						\
+_ELF_DEFINE_EF(EF_ARM_APCS_FLOAT,   0x00000010UL,			\
+	"GNU EABI extension")						\
+_ELF_DEFINE_EF(EF_ARM_PIC,          0x00000020UL,			\
+	"GNU EABI extension")						\
+_ELF_DEFINE_EF(EF_ARM_ALIGN8,       0x00000040UL,			\
+	"GNU EABI extension")						\
+_ELF_DEFINE_EF(EF_ARM_NEW_ABI,      0x00000080UL,			\
+	"GNU EABI extension")						\
+_ELF_DEFINE_EF(EF_ARM_OLD_ABI,      0x00000100UL,			\
+	"GNU EABI extension")						\
+_ELF_DEFINE_EF(EF_ARM_SOFT_FLOAT,   0x00000200UL,			\
+	"GNU EABI extension")						\
+_ELF_DEFINE_EF(EF_ARM_VFP_FLOAT,    0x00000400UL,			\
+	"GNU EABI extension")						\
+_ELF_DEFINE_EF(EF_ARM_MAVERICK_FLOAT, 0x00000800UL,			\
+	"GNU EABI extension")						\
+_ELF_DEFINE_EF(EF_MIPS_NOREORDER,   0x00000001UL,			\
+	"at least one .noreorder directive appeared in the source")	\
+_ELF_DEFINE_EF(EF_MIPS_PIC,         0x00000002UL,			\
+	"file contains position independent code")			\
+_ELF_DEFINE_EF(EF_MIPS_CPIC,        0x00000004UL,			\
+	"file's code uses standard conventions for calling PIC")	\
+_ELF_DEFINE_EF(EF_MIPS_UCODE,       0x00000010UL,			\
+	"file contains UCODE (obsolete)")				\
+_ELF_DEFINE_EF(EF_MIPS_ABI2,        0x00000020UL,			\
+	"file follows MIPS III 32-bit ABI")				\
+_ELF_DEFINE_EF(EF_MIPS_OPTIONS_FIRST, 0x00000080UL,			\
+	"ld(1) should process .MIPS.options section first")		\
+_ELF_DEFINE_EF(EF_MIPS_ARCH_ASE,    0x0F000000UL,			\
+	"file uses application-specific architectural extensions")	\
+_ELF_DEFINE_EF(EF_MIPS_ARCH_ASE_MDMX, 0x08000000UL,			\
+	"file uses MDMX multimedia extensions")				\
+_ELF_DEFINE_EF(EF_MIPS_ARCH_ASE_M16, 0x04000000UL,			\
+	"file uses MIPS-16 ISA extensions")				\
+_ELF_DEFINE_EF(EF_MIPS_ARCH,         0xF0000000UL,			\
+	"4-bit MIPS architecture field")				\
+_ELF_DEFINE_EF(EF_PPC_EMB,          0x80000000UL,			\
+	"Embedded PowerPC flag")					\
+_ELF_DEFINE_EF(EF_PPC_RELOCATABLE,  0x00010000UL,			\
+	"-mrelocatable flag")						\
+_ELF_DEFINE_EF(EF_PPC_RELOCATABLE_LIB, 0x00008000UL,			\
+	"-mrelocatable-lib flag")					\
+_ELF_DEFINE_EF(EF_SPARC_EXT_MASK,   0x00ffff00UL,			\
+	"Vendor Extension mask")					\
+_ELF_DEFINE_EF(EF_SPARC_32PLUS,     0x00000100UL,			\
+	"Generic V8+ features")						\
+_ELF_DEFINE_EF(EF_SPARC_SUN_US1,    0x00000200UL,			\
+	"Sun UltraSPARCTM 1 Extensions")				\
+_ELF_DEFINE_EF(EF_SPARC_HAL_R1,     0x00000400UL, "HAL R1 Extensions")	\
+_ELF_DEFINE_EF(EF_SPARC_SUN_US3,    0x00000800UL,			\
+	"Sun UltraSPARC 3 Extensions")					\
+_ELF_DEFINE_EF(EF_SPARCV9_MM,       0x00000003UL,			\
+	"Mask for Memory Model")					\
+_ELF_DEFINE_EF(EF_SPARCV9_TSO,      0x00000000UL,			\
+	"Total Store Ordering")						\
+_ELF_DEFINE_EF(EF_SPARCV9_PSO,      0x00000001UL,			\
+	"Partial Store Ordering")					\
+_ELF_DEFINE_EF(EF_SPARCV9_RMO,      0x00000002UL,			\
+	"Relaxed Memory Ordering")
+
+#undef	_ELF_DEFINE_EF
+#define	_ELF_DEFINE_EF(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_EHDR_FLAGS()
+	EF__LAST__
+};
+
+/*
+ * Offsets in the `ei_ident[]` field of an ELF executable header.
+ */
+#define	_ELF_DEFINE_EI_OFFSETS()			\
+_ELF_DEFINE_EI(EI_MAG0,     0, "magic number")		\
+_ELF_DEFINE_EI(EI_MAG1,     1, "magic number")		\
+_ELF_DEFINE_EI(EI_MAG2,     2, "magic number")		\
+_ELF_DEFINE_EI(EI_MAG3,     3, "magic number")		\
+_ELF_DEFINE_EI(EI_CLASS,    4, "file class")		\
+_ELF_DEFINE_EI(EI_DATA,     5, "data encoding")		\
+_ELF_DEFINE_EI(EI_VERSION,  6, "file version")		\
+_ELF_DEFINE_EI(EI_OSABI,    7, "OS ABI kind")		\
+_ELF_DEFINE_EI(EI_ABIVERSION, 8, "OS ABI version")	\
+_ELF_DEFINE_EI(EI_PAD,	    9, "padding start")		\
+_ELF_DEFINE_EI(EI_NIDENT,  16, "total size")
+
+#undef	_ELF_DEFINE_EI
+#define	_ELF_DEFINE_EI(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_EI_OFFSETS()
+	EI__LAST__
+};
+
+/*
+ * The ELF class of an object.
+ */
+#define	_ELF_DEFINE_ELFCLASS()				\
+_ELF_DEFINE_EC(ELFCLASSNONE, 0, "Unknown ELF class")	\
+_ELF_DEFINE_EC(ELFCLASS32,   1, "32 bit objects")	\
+_ELF_DEFINE_EC(ELFCLASS64,   2, "64 bit objects")
+
+#undef	_ELF_DEFINE_EC
+#define	_ELF_DEFINE_EC(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_ELFCLASS()
+	EC__LAST__
+};
+
+/*
+ * Endianness of data in an ELF object.
+ */
+
+#define	_ELF_DEFINE_ELF_DATA_ENDIANNESS()			\
+_ELF_DEFINE_ED(ELFDATANONE, 0, "Unknown data endianness")	\
+_ELF_DEFINE_ED(ELFDATA2LSB, 1, "little endian")			\
+_ELF_DEFINE_ED(ELFDATA2MSB, 2, "big endian")
+
+#undef	_ELF_DEFINE_ED
+#define	_ELF_DEFINE_ED(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_ELF_DATA_ENDIANNESS()
+	ED__LAST__
+};
+
+/*
+ * Values of the magic numbers used in identification array.
+ */
+#define	_ELF_DEFINE_ELF_MAGIC()			\
+_ELF_DEFINE_EMAG(ELFMAG0, 0x7FU)		\
+_ELF_DEFINE_EMAG(ELFMAG1, 'E')			\
+_ELF_DEFINE_EMAG(ELFMAG2, 'L')			\
+_ELF_DEFINE_EMAG(ELFMAG3, 'F')
+
+#undef	_ELF_DEFINE_EMAG
+#define	_ELF_DEFINE_EMAG(N, V)		N = V ,
+enum {
+	_ELF_DEFINE_ELF_MAGIC()
+	ELFMAG__LAST__
+};
+
+/*
+ * ELF OS ABI field.
+ */
+#define	_ELF_DEFINE_ELF_OSABI()						\
+_ELF_DEFINE_EABI(ELFOSABI_NONE,       0,				\
+	"No extensions or unspecified")					\
+_ELF_DEFINE_EABI(ELFOSABI_SYSV,       0, "SYSV")			\
+_ELF_DEFINE_EABI(ELFOSABI_HPUX,       1, "Hewlett-Packard HP-UX")	\
+_ELF_DEFINE_EABI(ELFOSABI_NETBSD,     2, "NetBSD")			\
+_ELF_DEFINE_EABI(ELFOSABI_GNU,        3, "GNU")				\
+_ELF_DEFINE_EABI(ELFOSABI_HURD,       4, "GNU/HURD")			\
+_ELF_DEFINE_EABI(ELFOSABI_86OPEN,     5, "86Open Common ABI")		\
+_ELF_DEFINE_EABI(ELFOSABI_SOLARIS,    6, "Sun Solaris")			\
+_ELF_DEFINE_EABI(ELFOSABI_AIX,        7, "AIX")				\
+_ELF_DEFINE_EABI(ELFOSABI_IRIX,       8, "IRIX")			\
+_ELF_DEFINE_EABI(ELFOSABI_FREEBSD,    9, "FreeBSD")			\
+_ELF_DEFINE_EABI(ELFOSABI_TRU64,      10, "Compaq TRU64 UNIX")		\
+_ELF_DEFINE_EABI(ELFOSABI_MODESTO,    11, "Novell Modesto")		\
+_ELF_DEFINE_EABI(ELFOSABI_OPENBSD,    12, "Open BSD")			\
+_ELF_DEFINE_EABI(ELFOSABI_OPENVMS,    13, "Open VMS")			\
+_ELF_DEFINE_EABI(ELFOSABI_NSK,        14,				\
+	"Hewlett-Packard Non-Stop Kernel")				\
+_ELF_DEFINE_EABI(ELFOSABI_AROS,       15, "Amiga Research OS")		\
+_ELF_DEFINE_EABI(ELFOSABI_FENIXOS,    16,				\
+	"The FenixOS highly scalable multi-core OS")			\
+_ELF_DEFINE_EABI(ELFOSABI_CLOUDABI,   17, "Nuxi CloudABI")		\
+_ELF_DEFINE_EABI(ELFOSABI_ARM_AEABI,  64,				\
+	"ARM specific symbol versioning extensions")			\
+_ELF_DEFINE_EABI(ELFOSABI_ARM,        97, "ARM ABI")			\
+_ELF_DEFINE_EABI(ELFOSABI_STANDALONE, 255,				\
+	"Standalone (embedded) application")
+
+#undef	_ELF_DEFINE_EABI
+#define	_ELF_DEFINE_EABI(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_ELF_OSABI()
+	ELFOSABI__LAST__
+};
+
+#define	ELFOSABI_LINUX			ELFOSABI_GNU
+
+/*
+ * ELF Machine types: (EM_*).
+ */
+#define	_ELF_DEFINE_ELF_MACHINES()					\
+_ELF_DEFINE_EM(EM_NONE,             0, "No machine")			\
+_ELF_DEFINE_EM(EM_M32,              1, "AT&T WE 32100")			\
+_ELF_DEFINE_EM(EM_SPARC,            2, "SPARC")				\
+_ELF_DEFINE_EM(EM_386,              3, "Intel 80386")			\
+_ELF_DEFINE_EM(EM_68K,              4, "Motorola 68000")		\
+_ELF_DEFINE_EM(EM_88K,              5, "Motorola 88000")		\
+_ELF_DEFINE_EM(EM_IAMCU,            6, "Intel MCU")			\
+_ELF_DEFINE_EM(EM_860,              7, "Intel 80860")			\
+_ELF_DEFINE_EM(EM_MIPS,             8, "MIPS I Architecture")		\
+_ELF_DEFINE_EM(EM_S370,             9, "IBM System/370 Processor")	\
+_ELF_DEFINE_EM(EM_MIPS_RS3_LE,      10, "MIPS RS3000 Little-endian")	\
+_ELF_DEFINE_EM(EM_PARISC,           15, "Hewlett-Packard PA-RISC")	\
+_ELF_DEFINE_EM(EM_VPP500,           17, "Fujitsu VPP500")		\
+_ELF_DEFINE_EM(EM_SPARC32PLUS,      18,					\
+	"Enhanced instruction set SPARC")				\
+_ELF_DEFINE_EM(EM_960,              19, "Intel 80960")			\
+_ELF_DEFINE_EM(EM_PPC,              20, "PowerPC")			\
+_ELF_DEFINE_EM(EM_PPC64,            21, "64-bit PowerPC")		\
+_ELF_DEFINE_EM(EM_S390,             22, "IBM System/390 Processor")	\
+_ELF_DEFINE_EM(EM_SPU,              23, "IBM SPU/SPC")			\
+_ELF_DEFINE_EM(EM_V800,             36, "NEC V800")			\
+_ELF_DEFINE_EM(EM_FR20,             37, "Fujitsu FR20")			\
+_ELF_DEFINE_EM(EM_RH32,             38, "TRW RH-32")			\
+_ELF_DEFINE_EM(EM_RCE,              39, "Motorola RCE")			\
+_ELF_DEFINE_EM(EM_ARM,              40, "Advanced RISC Machines ARM")	\
+_ELF_DEFINE_EM(EM_ALPHA,            41, "Digital Alpha")		\
+_ELF_DEFINE_EM(EM_SH,               42, "Hitachi SH")			\
+_ELF_DEFINE_EM(EM_SPARCV9,          43, "SPARC Version 9")		\
+_ELF_DEFINE_EM(EM_TRICORE,          44,					\
+	"Siemens TriCore embedded processor")				\
+_ELF_DEFINE_EM(EM_ARC,              45,					\
+	"Argonaut RISC Core, Argonaut Technologies Inc.")		\
+_ELF_DEFINE_EM(EM_H8_300,           46, "Hitachi H8/300")		\
+_ELF_DEFINE_EM(EM_H8_300H,          47, "Hitachi H8/300H")		\
+_ELF_DEFINE_EM(EM_H8S,              48, "Hitachi H8S")			\
+_ELF_DEFINE_EM(EM_H8_500,           49, "Hitachi H8/500")		\
+_ELF_DEFINE_EM(EM_IA_64,            50,					\
+	"Intel IA-64 processor architecture")				\
+_ELF_DEFINE_EM(EM_MIPS_X,           51, "Stanford MIPS-X")		\
+_ELF_DEFINE_EM(EM_COLDFIRE,         52, "Motorola ColdFire")		\
+_ELF_DEFINE_EM(EM_68HC12,           53, "Motorola M68HC12")		\
+_ELF_DEFINE_EM(EM_MMA,              54,					\
+	"Fujitsu MMA Multimedia Accelerator")				\
+_ELF_DEFINE_EM(EM_PCP,              55, "Siemens PCP")			\
+_ELF_DEFINE_EM(EM_NCPU,             56,					\
+	"Sony nCPU embedded RISC processor")				\
+_ELF_DEFINE_EM(EM_NDR1,             57, "Denso NDR1 microprocessor")	\
+_ELF_DEFINE_EM(EM_STARCORE,         58, "Motorola Star*Core processor")	\
+_ELF_DEFINE_EM(EM_ME16,             59, "Toyota ME16 processor")	\
+_ELF_DEFINE_EM(EM_ST100,            60,					\
+	"STMicroelectronics ST100 processor")				\
+_ELF_DEFINE_EM(EM_TINYJ,            61,					\
+	"Advanced Logic Corp. TinyJ embedded processor family")		\
+_ELF_DEFINE_EM(EM_X86_64,           62, "AMD x86-64 architecture")	\
+_ELF_DEFINE_EM(EM_PDSP,             63, "Sony DSP Processor")		\
+_ELF_DEFINE_EM(EM_PDP10,            64,					\
+	"Digital Equipment Corp. PDP-10")				\
+_ELF_DEFINE_EM(EM_PDP11,            65,					\
+	"Digital Equipment Corp. PDP-11")				\
+_ELF_DEFINE_EM(EM_FX66,             66, "Siemens FX66 microcontroller")	\
+_ELF_DEFINE_EM(EM_ST9PLUS,          67,					\
+	"STMicroelectronics ST9+ 8/16 bit microcontroller")		\
+_ELF_DEFINE_EM(EM_ST7,              68,					\
+	"STMicroelectronics ST7 8-bit microcontroller")			\
+_ELF_DEFINE_EM(EM_68HC16,           69,					\
+	"Motorola MC68HC16 Microcontroller")				\
+_ELF_DEFINE_EM(EM_68HC11,           70,					\
+	"Motorola MC68HC11 Microcontroller")				\
+_ELF_DEFINE_EM(EM_68HC08,           71,					\
+	"Motorola MC68HC08 Microcontroller")				\
+_ELF_DEFINE_EM(EM_68HC05,           72,					\
+	"Motorola MC68HC05 Microcontroller")				\
+_ELF_DEFINE_EM(EM_SVX,              73, "Silicon Graphics SVx")		\
+_ELF_DEFINE_EM(EM_ST19,             74,					\
+	"STMicroelectronics ST19 8-bit microcontroller")		\
+_ELF_DEFINE_EM(EM_VAX,              75, "Digital VAX")			\
+_ELF_DEFINE_EM(EM_CRIS,             76,					\
+	"Axis Communications 32-bit embedded processor")		\
+_ELF_DEFINE_EM(EM_JAVELIN,          77,					\
+	"Infineon Technologies 32-bit embedded processor")		\
+_ELF_DEFINE_EM(EM_FIREPATH,         78,					\
+	"Element 14 64-bit DSP Processor")				\
+_ELF_DEFINE_EM(EM_ZSP,              79,					\
+	"LSI Logic 16-bit DSP Processor")				\
+_ELF_DEFINE_EM(EM_MMIX,             80,					\
+	"Donald Knuth's educational 64-bit processor")			\
+_ELF_DEFINE_EM(EM_HUANY,            81,					\
+	"Harvard University machine-independent object files")		\
+_ELF_DEFINE_EM(EM_PRISM,            82, "SiTera Prism")			\
+_ELF_DEFINE_EM(EM_AVR,              83,					\
+	"Atmel AVR 8-bit microcontroller")				\
+_ELF_DEFINE_EM(EM_FR30,             84, "Fujitsu FR30")			\
+_ELF_DEFINE_EM(EM_D10V,             85, "Mitsubishi D10V")		\
+_ELF_DEFINE_EM(EM_D30V,             86, "Mitsubishi D30V")		\
+_ELF_DEFINE_EM(EM_V850,             87, "NEC v850")			\
+_ELF_DEFINE_EM(EM_M32R,             88, "Mitsubishi M32R")		\
+_ELF_DEFINE_EM(EM_MN10300,          89, "Matsushita MN10300")		\
+_ELF_DEFINE_EM(EM_MN10200,          90, "Matsushita MN10200")		\
+_ELF_DEFINE_EM(EM_PJ,               91, "picoJava")			\
+_ELF_DEFINE_EM(EM_OPENRISC,         92,					\
+	"OpenRISC 32-bit embedded processor")				\
+_ELF_DEFINE_EM(EM_ARC_COMPACT,      93,					\
+	"ARC International ARCompact processor")			\
+_ELF_DEFINE_EM(EM_XTENSA,           94,					\
+	"Tensilica Xtensa Architecture")				\
+_ELF_DEFINE_EM(EM_VIDEOCORE,        95,					\
+	"Alphamosaic VideoCore processor")				\
+_ELF_DEFINE_EM(EM_TMM_GPP,          96,					\
+	"Thompson Multimedia General Purpose Processor")		\
+_ELF_DEFINE_EM(EM_NS32K,            97,					\
+	"National Semiconductor 32000 series")				\
+_ELF_DEFINE_EM(EM_TPC,              98, "Tenor Network TPC processor")	\
+_ELF_DEFINE_EM(EM_SNP1K,            99, "Trebia SNP 1000 processor")	\
+_ELF_DEFINE_EM(EM_ST200,            100,				\
+	"STMicroelectronics (www.st.com) ST200 microcontroller")	\
+_ELF_DEFINE_EM(EM_IP2K,             101,				\
+	"Ubicom IP2xxx microcontroller family")				\
+_ELF_DEFINE_EM(EM_MAX,              102, "MAX Processor")		\
+_ELF_DEFINE_EM(EM_CR,               103,				\
+	"National Semiconductor CompactRISC microprocessor")		\
+_ELF_DEFINE_EM(EM_F2MC16,           104, "Fujitsu F2MC16")		\
+_ELF_DEFINE_EM(EM_MSP430,           105,				\
+	"Texas Instruments embedded microcontroller msp430")		\
+_ELF_DEFINE_EM(EM_BLACKFIN,         106,				\
+	"Analog Devices Blackfin (DSP) processor")			\
+_ELF_DEFINE_EM(EM_SE_C33,           107,				\
+	"S1C33 Family of Seiko Epson processors")			\
+_ELF_DEFINE_EM(EM_SEP,              108,				\
+	"Sharp embedded microprocessor")				\
+_ELF_DEFINE_EM(EM_ARCA,             109, "Arca RISC Microprocessor")	\
+_ELF_DEFINE_EM(EM_UNICORE,          110,				\
+	"Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University") \
+_ELF_DEFINE_EM(EM_EXCESS,           111,				\
+	"eXcess: 16/32/64-bit configurable embedded CPU")		\
+_ELF_DEFINE_EM(EM_DXP,              112,				\
+	"Icera Semiconductor Inc. Deep Execution Processor")		\
+_ELF_DEFINE_EM(EM_ALTERA_NIOS2,     113,				\
+	"Altera Nios II soft-core processor")				\
+_ELF_DEFINE_EM(EM_CRX,              114,				\
+	"National Semiconductor CompactRISC CRX microprocessor")	\
+_ELF_DEFINE_EM(EM_XGATE,            115,				\
+	"Motorola XGATE embedded processor")				\
+_ELF_DEFINE_EM(EM_C166,             116,				\
+	"Infineon C16x/XC16x processor")				\
+_ELF_DEFINE_EM(EM_M16C,             117,				\
+	"Renesas M16C series microprocessors")				\
+_ELF_DEFINE_EM(EM_DSPIC30F,         118,				\
+	"Microchip Technology dsPIC30F Digital Signal Controller")	\
+_ELF_DEFINE_EM(EM_CE,               119,				\
+	"Freescale Communication Engine RISC core")			\
+_ELF_DEFINE_EM(EM_M32C,             120,				\
+	"Renesas M32C series microprocessors")				\
+_ELF_DEFINE_EM(EM_TSK3000,          131, "Altium TSK3000 core")		\
+_ELF_DEFINE_EM(EM_RS08,             132,				\
+	"Freescale RS08 embedded processor")				\
+_ELF_DEFINE_EM(EM_SHARC,            133,				\
+	"Analog Devices SHARC family of 32-bit DSP processors")		\
+_ELF_DEFINE_EM(EM_ECOG2,            134,				\
+	"Cyan Technology eCOG2 microprocessor")				\
+_ELF_DEFINE_EM(EM_SCORE7,           135,				\
+	"Sunplus S+core7 RISC processor")				\
+_ELF_DEFINE_EM(EM_DSP24,            136,				\
+	"New Japan Radio (NJR) 24-bit DSP Processor")			\
+_ELF_DEFINE_EM(EM_VIDEOCORE3,       137,				\
+	"Broadcom VideoCore III processor")				\
+_ELF_DEFINE_EM(EM_LATTICEMICO32,    138,				\
+	"RISC processor for Lattice FPGA architecture")			\
+_ELF_DEFINE_EM(EM_SE_C17,           139, "Seiko Epson C17 family")	\
+_ELF_DEFINE_EM(EM_TI_C6000,         140,				\
+	"The Texas Instruments TMS320C6000 DSP family")			\
+_ELF_DEFINE_EM(EM_TI_C2000,         141,				\
+	"The Texas Instruments TMS320C2000 DSP family")			\
+_ELF_DEFINE_EM(EM_TI_C5500,         142,				\
+	"The Texas Instruments TMS320C55x DSP family")			\
+_ELF_DEFINE_EM(EM_MMDSP_PLUS,       160,				\
+	"STMicroelectronics 64bit VLIW Data Signal Processor")		\
+_ELF_DEFINE_EM(EM_CYPRESS_M8C,      161, "Cypress M8C microprocessor")	\
+_ELF_DEFINE_EM(EM_R32C,             162,				\
+	"Renesas R32C series microprocessors")				\
+_ELF_DEFINE_EM(EM_TRIMEDIA,         163,				\
+	"NXP Semiconductors TriMedia architecture family")		\
+_ELF_DEFINE_EM(EM_QDSP6,            164, "QUALCOMM DSP6 Processor")	\
+_ELF_DEFINE_EM(EM_8051,             165, "Intel 8051 and variants")	\
+_ELF_DEFINE_EM(EM_STXP7X,           166,				\
+	"STMicroelectronics STxP7x family of configurable and extensible RISC processors") \
+_ELF_DEFINE_EM(EM_NDS32,            167,				\
+	"Andes Technology compact code size embedded RISC processor family") \
+_ELF_DEFINE_EM(EM_ECOG1,            168,				\
+	"Cyan Technology eCOG1X family")				\
+_ELF_DEFINE_EM(EM_ECOG1X,           168,				\
+	"Cyan Technology eCOG1X family")				\
+_ELF_DEFINE_EM(EM_MAXQ30,           169,				\
+	"Dallas Semiconductor MAXQ30 Core Micro-controllers")		\
+_ELF_DEFINE_EM(EM_XIMO16,           170,				\
+	"New Japan Radio (NJR) 16-bit DSP Processor")			\
+_ELF_DEFINE_EM(EM_MANIK,            171,				\
+	"M2000 Reconfigurable RISC Microprocessor")			\
+_ELF_DEFINE_EM(EM_CRAYNV2,          172,				\
+	"Cray Inc. NV2 vector architecture")				\
+_ELF_DEFINE_EM(EM_RX,               173, "Renesas RX family")		\
+_ELF_DEFINE_EM(EM_METAG,            174,				\
+	"Imagination Technologies META processor architecture")		\
+_ELF_DEFINE_EM(EM_MCST_ELBRUS,      175,				\
+	"MCST Elbrus general purpose hardware architecture")		\
+_ELF_DEFINE_EM(EM_ECOG16,           176,				\
+	"Cyan Technology eCOG16 family")				\
+_ELF_DEFINE_EM(EM_CR16,             177,				\
+	"National Semiconductor CompactRISC CR16 16-bit microprocessor") \
+_ELF_DEFINE_EM(EM_ETPU,             178,				\
+	"Freescale Extended Time Processing Unit")			\
+_ELF_DEFINE_EM(EM_SLE9X,            179,				\
+	"Infineon Technologies SLE9X core")				\
+_ELF_DEFINE_EM(EM_AARCH64,          183,				\
+	"AArch64 (64-bit ARM)")						\
+_ELF_DEFINE_EM(EM_AVR32,            185,				\
+	"Atmel Corporation 32-bit microprocessor family")		\
+_ELF_DEFINE_EM(EM_STM8,             186,				\
+	"STMicroeletronics STM8 8-bit microcontroller")			\
+_ELF_DEFINE_EM(EM_TILE64,           187,				\
+	"Tilera TILE64 multicore architecture family")			\
+_ELF_DEFINE_EM(EM_TILEPRO,          188,				\
+	"Tilera TILEPro multicore architecture family")			\
+_ELF_DEFINE_EM(EM_MICROBLAZE,       189,				\
+	"Xilinx MicroBlaze 32-bit RISC soft processor core")		\
+_ELF_DEFINE_EM(EM_CUDA,             190, "NVIDIA CUDA architecture")	\
+_ELF_DEFINE_EM(EM_TILEGX,           191,				\
+	"Tilera TILE-Gx multicore architecture family")			\
+_ELF_DEFINE_EM(EM_CLOUDSHIELD,      192,				\
+	"CloudShield architecture family")				\
+_ELF_DEFINE_EM(EM_COREA_1ST,        193,				\
+	"KIPO-KAIST Core-A 1st generation processor family")		\
+_ELF_DEFINE_EM(EM_COREA_2ND,        194,				\
+	"KIPO-KAIST Core-A 2nd generation processor family")		\
+_ELF_DEFINE_EM(EM_ARC_COMPACT2,     195, "Synopsys ARCompact V2")	\
+_ELF_DEFINE_EM(EM_OPEN8,            196,				\
+	"Open8 8-bit RISC soft processor core")				\
+_ELF_DEFINE_EM(EM_RL78,             197, "Renesas RL78 family")		\
+_ELF_DEFINE_EM(EM_VIDEOCORE5,       198, "Broadcom VideoCore V processor") \
+_ELF_DEFINE_EM(EM_78KOR,            199, "Renesas 78KOR family")	\
+_ELF_DEFINE_EM(EM_56800EX,          200,				\
+	"Freescale 56800EX Digital Signal Controller")			\
+_ELF_DEFINE_EM(EM_BA1,              201, "Beyond BA1 CPU architecture")	\
+_ELF_DEFINE_EM(EM_BA2,              202, "Beyond BA2 CPU architecture")	\
+_ELF_DEFINE_EM(EM_XCORE,            203, "XMOS xCORE processor family") \
+_ELF_DEFINE_EM(EM_MCHP_PIC,         204, "Microchip 8-bit PIC(r) family") \
+_ELF_DEFINE_EM(EM_INTEL205,         205, "Reserved by Intel")           \
+_ELF_DEFINE_EM(EM_INTEL206,         206, "Reserved by Intel")           \
+_ELF_DEFINE_EM(EM_INTEL207,         207, "Reserved by Intel")           \
+_ELF_DEFINE_EM(EM_INTEL208,         208, "Reserved by Intel")           \
+_ELF_DEFINE_EM(EM_INTEL209,         209, "Reserved by Intel")           \
+_ELF_DEFINE_EM(EM_KM32,             210, "KM211 KM32 32-bit processor") \
+_ELF_DEFINE_EM(EM_KMX32,            211, "KM211 KMX32 32-bit processor") \
+_ELF_DEFINE_EM(EM_KMX16,            212, "KM211 KMX16 16-bit processor") \
+_ELF_DEFINE_EM(EM_KMX8,             213, "KM211 KMX8 8-bit processor")  \
+_ELF_DEFINE_EM(EM_KVARC,            214, "KM211 KMX32 KVARC processor") \
+_ELF_DEFINE_EM(EM_RISCV,            243, "RISC-V")
+
+#undef	_ELF_DEFINE_EM
+#define	_ELF_DEFINE_EM(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_ELF_MACHINES()
+	EM__LAST__
+};
+
+/* Other synonyms. */
+#define	EM_AMD64		EM_X86_64
+#define	EM_ARC_A5		EM_ARC_COMPACT
+
+/*
+ * ELF file types: (ET_*).
+ */
+#define	_ELF_DEFINE_ELF_TYPES()						\
+_ELF_DEFINE_ET(ET_NONE,   0,	    "No file type")			\
+_ELF_DEFINE_ET(ET_REL,    1, 	    "Relocatable object")		\
+_ELF_DEFINE_ET(ET_EXEC,   2, 	    "Executable")			\
+_ELF_DEFINE_ET(ET_DYN,    3, 	    "Shared object")			\
+_ELF_DEFINE_ET(ET_CORE,   4, 	    "Core file")			\
+_ELF_DEFINE_ET(ET_LOOS,   0xFE00U,  "Begin OS-specific range")		\
+_ELF_DEFINE_ET(ET_HIOS,   0xFEFFU,  "End OS-specific range")		\
+_ELF_DEFINE_ET(ET_LOPROC, 0xFF00U,  "Begin processor-specific range")	\
+_ELF_DEFINE_ET(ET_HIPROC, 0xFFFFU,  "End processor-specific range")
+
+#undef	_ELF_DEFINE_ET
+#define	_ELF_DEFINE_ET(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_ELF_TYPES()
+	ET__LAST__
+};
+
+/* ELF file format version numbers. */
+#define	EV_NONE		0
+#define	EV_CURRENT	1
+
+/*
+ * Flags for section groups.
+ */
+#define	GRP_COMDAT 	0x1		/* COMDAT semantics */
+#define	GRP_MASKOS 	0x0ff00000	/* OS-specific flags */
+#define	GRP_MASKPROC 	0xf0000000	/* processor-specific flags */
+
+/*
+ * Flags / mask for .gnu.versym sections.
+ */
+#define	VERSYM_VERSION	0x7fff
+#define	VERSYM_HIDDEN	0x8000
+
+/*
+ * Flags used by program header table entries.
+ */
+
+#define	_ELF_DEFINE_PHDR_FLAGS()					\
+_ELF_DEFINE_PF(PF_X,                0x1, "Execute")			\
+_ELF_DEFINE_PF(PF_W,                0x2, "Write")			\
+_ELF_DEFINE_PF(PF_R,                0x4, "Read")			\
+_ELF_DEFINE_PF(PF_MASKOS,           0x0ff00000, "OS-specific flags")	\
+_ELF_DEFINE_PF(PF_MASKPROC,         0xf0000000, "Processor-specific flags") \
+_ELF_DEFINE_PF(PF_ARM_SB,           0x10000000,				\
+	"segment contains the location addressed by the static base")	\
+_ELF_DEFINE_PF(PF_ARM_PI,           0x20000000,				\
+	"segment is position-independent")				\
+_ELF_DEFINE_PF(PF_ARM_ABS,          0x40000000,				\
+	"segment must be loaded at its base address")
+
+#undef	_ELF_DEFINE_PF
+#define	_ELF_DEFINE_PF(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_PHDR_FLAGS()
+	PF__LAST__
+};
+
+/*
+ * Types of program header table entries.
+ */
+
+#define	_ELF_DEFINE_PHDR_TYPES()				\
+_ELF_DEFINE_PT(PT_NULL,             0, "ignored entry")		\
+_ELF_DEFINE_PT(PT_LOAD,             1, "loadable segment")	\
+_ELF_DEFINE_PT(PT_DYNAMIC,          2,				\
+	"contains dynamic linking information")			\
+_ELF_DEFINE_PT(PT_INTERP,           3, "names an interpreter")	\
+_ELF_DEFINE_PT(PT_NOTE,             4, "auxiliary information")	\
+_ELF_DEFINE_PT(PT_SHLIB,            5, "reserved")		\
+_ELF_DEFINE_PT(PT_PHDR,             6,				\
+	"describes the program header itself")			\
+_ELF_DEFINE_PT(PT_TLS,              7, "thread local storage")	\
+_ELF_DEFINE_PT(PT_LOOS,             0x60000000UL,		\
+	"start of OS-specific range")				\
+_ELF_DEFINE_PT(PT_SUNW_UNWIND,      0x6464E550UL,		\
+	"Solaris/amd64 stack unwind tables")			\
+_ELF_DEFINE_PT(PT_GNU_EH_FRAME,     0x6474E550UL,		\
+	"GCC generated .eh_frame_hdr segment")			\
+_ELF_DEFINE_PT(PT_GNU_STACK,	    0x6474E551UL,		\
+	"Stack flags")						\
+_ELF_DEFINE_PT(PT_GNU_RELRO,	    0x6474E552UL,		\
+	"Segment becomes read-only after relocation")		\
+_ELF_DEFINE_PT(PT_OPENBSD_RANDOMIZE,0x65A3DBE6UL,		\
+	"Segment filled with random data")			\
+_ELF_DEFINE_PT(PT_OPENBSD_WXNEEDED, 0x65A3DBE7UL,		\
+	"Program violates W^X")					\
+_ELF_DEFINE_PT(PT_OPENBSD_BOOTDATA, 0x65A41BE6UL,		\
+	"Boot data")						\
+_ELF_DEFINE_PT(PT_SUNWBSS,          0x6FFFFFFAUL,		\
+	"A Solaris .SUNW_bss section")				\
+_ELF_DEFINE_PT(PT_SUNWSTACK,        0x6FFFFFFBUL,		\
+	"A Solaris process stack")				\
+_ELF_DEFINE_PT(PT_SUNWDTRACE,       0x6FFFFFFCUL,		\
+	"Used by dtrace(1)")					\
+_ELF_DEFINE_PT(PT_SUNWCAP,          0x6FFFFFFDUL,		\
+	"Special hardware capability requirements")		\
+_ELF_DEFINE_PT(PT_HIOS,             0x6FFFFFFFUL,		\
+	"end of OS-specific range")				\
+_ELF_DEFINE_PT(PT_LOPROC,           0x70000000UL,		\
+	"start of processor-specific range")			\
+_ELF_DEFINE_PT(PT_ARM_ARCHEXT,      0x70000000UL,		\
+	"platform architecture compatibility information")	\
+_ELF_DEFINE_PT(PT_ARM_EXIDX,        0x70000001UL,		\
+	"exception unwind tables")				\
+_ELF_DEFINE_PT(PT_MIPS_REGINFO,     0x70000000UL,		\
+	"register usage information")				\
+_ELF_DEFINE_PT(PT_MIPS_RTPROC,      0x70000001UL,		\
+	"runtime procedure table")				\
+_ELF_DEFINE_PT(PT_MIPS_OPTIONS,     0x70000002UL,		\
+	"options segment")					\
+_ELF_DEFINE_PT(PT_HIPROC,           0x7FFFFFFFUL,		\
+	"end of processor-specific range")
+
+#undef	_ELF_DEFINE_PT
+#define	_ELF_DEFINE_PT(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_PHDR_TYPES()
+	PT__LAST__ = PT_HIPROC
+};
+
+/* synonyms. */
+#define	PT_ARM_UNWIND	PT_ARM_EXIDX
+#define	PT_HISUNW	PT_HIOS
+#define	PT_LOSUNW	PT_SUNWBSS
+
+/*
+ * Section flags.
+ */
+
+#define	_ELF_DEFINE_SECTION_FLAGS()					\
+_ELF_DEFINE_SHF(SHF_WRITE,           0x1,				\
+	"writable during program execution")				\
+_ELF_DEFINE_SHF(SHF_ALLOC,           0x2,				\
+	"occupies memory during program execution")			\
+_ELF_DEFINE_SHF(SHF_EXECINSTR,       0x4, "executable instructions")	\
+_ELF_DEFINE_SHF(SHF_MERGE,           0x10,				\
+	"may be merged to prevent duplication")				\
+_ELF_DEFINE_SHF(SHF_STRINGS,         0x20,				\
+	"NUL-terminated character strings")				\
+_ELF_DEFINE_SHF(SHF_INFO_LINK,       0x40,				\
+	"the sh_info field holds a link")				\
+_ELF_DEFINE_SHF(SHF_LINK_ORDER,      0x80,				\
+	"special ordering requirements during linking")			\
+_ELF_DEFINE_SHF(SHF_OS_NONCONFORMING, 0x100,				\
+	"requires OS-specific processing during linking")		\
+_ELF_DEFINE_SHF(SHF_GROUP,           0x200,				\
+	"member of a section group")					\
+_ELF_DEFINE_SHF(SHF_TLS,             0x400,				\
+	"holds thread-local storage")					\
+_ELF_DEFINE_SHF(SHF_COMPRESSED,      0x800,				\
+	"holds compressed data")					\
+_ELF_DEFINE_SHF(SHF_MASKOS,          0x0FF00000UL,			\
+	"bits reserved for OS-specific semantics")			\
+_ELF_DEFINE_SHF(SHF_AMD64_LARGE,     0x10000000UL,			\
+	"section uses large code model")				\
+_ELF_DEFINE_SHF(SHF_ENTRYSECT,       0x10000000UL,			\
+	"section contains an entry point (ARM)")			\
+_ELF_DEFINE_SHF(SHF_COMDEF,          0x80000000UL,			\
+	"section may be multiply defined in input to link step (ARM)")	\
+_ELF_DEFINE_SHF(SHF_MIPS_GPREL,      0x10000000UL,			\
+	"section must be part of global data area")			\
+_ELF_DEFINE_SHF(SHF_MIPS_MERGE,      0x20000000UL,			\
+	"section data should be merged to eliminate duplication")	\
+_ELF_DEFINE_SHF(SHF_MIPS_ADDR,       0x40000000UL,			\
+	"section data is addressed by default")				\
+_ELF_DEFINE_SHF(SHF_MIPS_STRING,     0x80000000UL,			\
+	"section data is string data by default")			\
+_ELF_DEFINE_SHF(SHF_MIPS_NOSTRIP,    0x08000000UL,			\
+	"section data may not be stripped")				\
+_ELF_DEFINE_SHF(SHF_MIPS_LOCAL,      0x04000000UL,			\
+	"section data local to process")				\
+_ELF_DEFINE_SHF(SHF_MIPS_NAMES,      0x02000000UL,			\
+	"linker must generate implicit hidden weak names")		\
+_ELF_DEFINE_SHF(SHF_MIPS_NODUPE,     0x01000000UL,			\
+	"linker must retain only one copy")				\
+_ELF_DEFINE_SHF(SHF_ORDERED,         0x40000000UL,			\
+	"section is ordered with respect to other sections")		\
+_ELF_DEFINE_SHF(SHF_EXCLUDE,	     0x80000000UL,			\
+	"section is excluded from executables and shared objects")	\
+_ELF_DEFINE_SHF(SHF_MASKPROC,        0xF0000000UL,			\
+	"bits reserved for processor-specific semantics")
+
+#undef	_ELF_DEFINE_SHF
+#define	_ELF_DEFINE_SHF(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_SECTION_FLAGS()
+	SHF__LAST__
+};
+
+/*
+ * Special section indices.
+ */
+#define _ELF_DEFINE_SECTION_INDICES()					\
+_ELF_DEFINE_SHN(SHN_UNDEF, 	0, 	 "undefined section")		\
+_ELF_DEFINE_SHN(SHN_LORESERVE, 	0xFF00U, "start of reserved area")	\
+_ELF_DEFINE_SHN(SHN_LOPROC, 	0xFF00U,				\
+	"start of processor-specific range")				\
+_ELF_DEFINE_SHN(SHN_BEFORE,	0xFF00U, "used for section ordering")	\
+_ELF_DEFINE_SHN(SHN_AFTER,	0xFF01U, "used for section ordering")	\
+_ELF_DEFINE_SHN(SHN_AMD64_LCOMMON, 0xFF02U, "large common block label") \
+_ELF_DEFINE_SHN(SHN_MIPS_ACOMMON, 0xFF00U,				\
+	"allocated common symbols in a DSO")				\
+_ELF_DEFINE_SHN(SHN_MIPS_TEXT,	0xFF01U, "Reserved (obsolete)")		\
+_ELF_DEFINE_SHN(SHN_MIPS_DATA,	0xFF02U, "Reserved (obsolete)")		\
+_ELF_DEFINE_SHN(SHN_MIPS_SCOMMON, 0xFF03U,				\
+	"gp-addressable common symbols")				\
+_ELF_DEFINE_SHN(SHN_MIPS_SUNDEFINED, 0xFF04U,				\
+	"gp-addressable undefined symbols")				\
+_ELF_DEFINE_SHN(SHN_MIPS_LCOMMON, 0xFF05U, "local common symbols")	\
+_ELF_DEFINE_SHN(SHN_MIPS_LUNDEFINED, 0xFF06U,				\
+	"local undefined symbols")					\
+_ELF_DEFINE_SHN(SHN_HIPROC, 	0xFF1FU,				\
+	"end of processor-specific range")				\
+_ELF_DEFINE_SHN(SHN_LOOS, 	0xFF20U,				\
+	"start of OS-specific range")					\
+_ELF_DEFINE_SHN(SHN_SUNW_IGNORE, 0xFF3FU, "used by dtrace")		\
+_ELF_DEFINE_SHN(SHN_HIOS, 	0xFF3FU,				\
+	"end of OS-specific range")					\
+_ELF_DEFINE_SHN(SHN_ABS, 	0xFFF1U, "absolute references")		\
+_ELF_DEFINE_SHN(SHN_COMMON, 	0xFFF2U, "references to COMMON areas")	\
+_ELF_DEFINE_SHN(SHN_XINDEX, 	0xFFFFU, "extended index")		\
+_ELF_DEFINE_SHN(SHN_HIRESERVE, 	0xFFFFU, "end of reserved area")
+
+#undef	_ELF_DEFINE_SHN
+#define	_ELF_DEFINE_SHN(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_SECTION_INDICES()
+	SHN__LAST__
+};
+
+/*
+ * Section types.
+ */
+
+#define	_ELF_DEFINE_SECTION_TYPES()					\
+_ELF_DEFINE_SHT(SHT_NULL,            0, "inactive header")		\
+_ELF_DEFINE_SHT(SHT_PROGBITS,        1, "program defined information")	\
+_ELF_DEFINE_SHT(SHT_SYMTAB,          2, "symbol table")			\
+_ELF_DEFINE_SHT(SHT_STRTAB,          3, "string table")			\
+_ELF_DEFINE_SHT(SHT_RELA,            4,					\
+	"relocation entries with addends")				\
+_ELF_DEFINE_SHT(SHT_HASH,            5, "symbol hash table")		\
+_ELF_DEFINE_SHT(SHT_DYNAMIC,         6,					\
+	"information for dynamic linking")				\
+_ELF_DEFINE_SHT(SHT_NOTE,            7, "additional notes")		\
+_ELF_DEFINE_SHT(SHT_NOBITS,          8, "section occupying no space")	\
+_ELF_DEFINE_SHT(SHT_REL,             9,					\
+	"relocation entries without addends")				\
+_ELF_DEFINE_SHT(SHT_SHLIB,           10, "reserved")			\
+_ELF_DEFINE_SHT(SHT_DYNSYM,          11, "symbol table")		\
+_ELF_DEFINE_SHT(SHT_INIT_ARRAY,      14,				\
+	"pointers to initialization functions")				\
+_ELF_DEFINE_SHT(SHT_FINI_ARRAY,      15,				\
+	"pointers to termination functions")				\
+_ELF_DEFINE_SHT(SHT_PREINIT_ARRAY,   16,				\
+	"pointers to functions called before initialization")		\
+_ELF_DEFINE_SHT(SHT_GROUP,           17, "defines a section group")	\
+_ELF_DEFINE_SHT(SHT_SYMTAB_SHNDX,    18,				\
+	"used for extended section numbering")				\
+_ELF_DEFINE_SHT(SHT_LOOS,            0x60000000UL,			\
+	"start of OS-specific range")					\
+_ELF_DEFINE_SHT(SHT_SUNW_dof,	     0x6FFFFFF4UL,			\
+	"used by dtrace")						\
+_ELF_DEFINE_SHT(SHT_SUNW_cap,	     0x6FFFFFF5UL,			\
+	"capability requirements")					\
+_ELF_DEFINE_SHT(SHT_GNU_ATTRIBUTES,  0x6FFFFFF5UL,			\
+	"object attributes")						\
+_ELF_DEFINE_SHT(SHT_SUNW_SIGNATURE,  0x6FFFFFF6UL,			\
+	"module verification signature")				\
+_ELF_DEFINE_SHT(SHT_GNU_HASH,	     0x6FFFFFF6UL,			\
+	"GNU Hash sections")						\
+_ELF_DEFINE_SHT(SHT_GNU_LIBLIST,     0x6FFFFFF7UL,			\
+	"List of libraries to be prelinked")				\
+_ELF_DEFINE_SHT(SHT_SUNW_ANNOTATE,   0x6FFFFFF7UL,			\
+	"special section where unresolved references are allowed")	\
+_ELF_DEFINE_SHT(SHT_SUNW_DEBUGSTR,   0x6FFFFFF8UL,			\
+	"debugging information")					\
+_ELF_DEFINE_SHT(SHT_CHECKSUM, 	     0x6FFFFFF8UL,			\
+	"checksum for dynamic shared objects")				\
+_ELF_DEFINE_SHT(SHT_SUNW_DEBUG,      0x6FFFFFF9UL,			\
+	"debugging information")					\
+_ELF_DEFINE_SHT(SHT_SUNW_move,       0x6FFFFFFAUL,			\
+	"information to handle partially initialized symbols")		\
+_ELF_DEFINE_SHT(SHT_SUNW_COMDAT,     0x6FFFFFFBUL,			\
+	"section supporting merging of multiple copies of data")	\
+_ELF_DEFINE_SHT(SHT_SUNW_syminfo,    0x6FFFFFFCUL,			\
+	"additional symbol information")				\
+_ELF_DEFINE_SHT(SHT_SUNW_verdef,     0x6FFFFFFDUL,			\
+	"symbol versioning information")				\
+_ELF_DEFINE_SHT(SHT_SUNW_verneed,    0x6FFFFFFEUL,			\
+	"symbol versioning requirements")				\
+_ELF_DEFINE_SHT(SHT_SUNW_versym,     0x6FFFFFFFUL,			\
+	"symbol versioning table")					\
+_ELF_DEFINE_SHT(SHT_HIOS,            0x6FFFFFFFUL,			\
+	"end of OS-specific range")					\
+_ELF_DEFINE_SHT(SHT_LOPROC,          0x70000000UL,			\
+	"start of processor-specific range")				\
+_ELF_DEFINE_SHT(SHT_ARM_EXIDX,       0x70000001UL,			\
+	"exception index table")					\
+_ELF_DEFINE_SHT(SHT_ARM_PREEMPTMAP,  0x70000002UL,			\
+	"BPABI DLL dynamic linking preemption map")			\
+_ELF_DEFINE_SHT(SHT_ARM_ATTRIBUTES,  0x70000003UL,			\
+	"object file compatibility attributes")				\
+_ELF_DEFINE_SHT(SHT_ARM_DEBUGOVERLAY, 0x70000004UL,			\
+	"overlay debug information")					\
+_ELF_DEFINE_SHT(SHT_ARM_OVERLAYSECTION, 0x70000005UL,			\
+	"overlay debug information")					\
+_ELF_DEFINE_SHT(SHT_MIPS_LIBLIST,    0x70000000UL,			\
+	"DSO library information used in link")				\
+_ELF_DEFINE_SHT(SHT_MIPS_MSYM,       0x70000001UL,			\
+	"MIPS symbol table extension")					\
+_ELF_DEFINE_SHT(SHT_MIPS_CONFLICT,   0x70000002UL,			\
+	"symbol conflicting with DSO-defined symbols ")			\
+_ELF_DEFINE_SHT(SHT_MIPS_GPTAB,      0x70000003UL,			\
+	"global pointer table")						\
+_ELF_DEFINE_SHT(SHT_MIPS_UCODE,      0x70000004UL,			\
+	"reserved")							\
+_ELF_DEFINE_SHT(SHT_MIPS_DEBUG,      0x70000005UL,			\
+	"reserved (obsolete debug information)")			\
+_ELF_DEFINE_SHT(SHT_MIPS_REGINFO,    0x70000006UL,			\
+	"register usage information")					\
+_ELF_DEFINE_SHT(SHT_MIPS_PACKAGE,    0x70000007UL,			\
+	"OSF reserved")							\
+_ELF_DEFINE_SHT(SHT_MIPS_PACKSYM,    0x70000008UL,			\
+	"OSF reserved")							\
+_ELF_DEFINE_SHT(SHT_MIPS_RELD,       0x70000009UL,			\
+	"dynamic relocation")						\
+_ELF_DEFINE_SHT(SHT_MIPS_IFACE,      0x7000000BUL,			\
+	"subprogram interface information")				\
+_ELF_DEFINE_SHT(SHT_MIPS_CONTENT,    0x7000000CUL,			\
+	"section content classification")				\
+_ELF_DEFINE_SHT(SHT_MIPS_OPTIONS,     0x7000000DUL,			\
+	"general options")						\
+_ELF_DEFINE_SHT(SHT_MIPS_DELTASYM,   0x7000001BUL,			\
+	"Delta C++: symbol table")					\
+_ELF_DEFINE_SHT(SHT_MIPS_DELTAINST,  0x7000001CUL,			\
+	"Delta C++: instance table")					\
+_ELF_DEFINE_SHT(SHT_MIPS_DELTACLASS, 0x7000001DUL,			\
+	"Delta C++: class table")					\
+_ELF_DEFINE_SHT(SHT_MIPS_DWARF,      0x7000001EUL,			\
+	"DWARF debug information")					\
+_ELF_DEFINE_SHT(SHT_MIPS_DELTADECL,  0x7000001FUL,			\
+	"Delta C++: declarations")					\
+_ELF_DEFINE_SHT(SHT_MIPS_SYMBOL_LIB, 0x70000020UL,			\
+	"symbol-to-library mapping")					\
+_ELF_DEFINE_SHT(SHT_MIPS_EVENTS,     0x70000021UL,			\
+	"event locations")						\
+_ELF_DEFINE_SHT(SHT_MIPS_TRANSLATE,  0x70000022UL,			\
+	"???")								\
+_ELF_DEFINE_SHT(SHT_MIPS_PIXIE,      0x70000023UL,			\
+	"special pixie sections")					\
+_ELF_DEFINE_SHT(SHT_MIPS_XLATE,      0x70000024UL,			\
+	"address translation table")					\
+_ELF_DEFINE_SHT(SHT_MIPS_XLATE_DEBUG, 0x70000025UL,			\
+	"SGI internal address translation table")			\
+_ELF_DEFINE_SHT(SHT_MIPS_WHIRL,      0x70000026UL,			\
+	"intermediate code")						\
+_ELF_DEFINE_SHT(SHT_MIPS_EH_REGION,  0x70000027UL,			\
+	"C++ exception handling region info")				\
+_ELF_DEFINE_SHT(SHT_MIPS_XLATE_OLD,  0x70000028UL,			\
+	"obsolete")							\
+_ELF_DEFINE_SHT(SHT_MIPS_PDR_EXCEPTION, 0x70000029UL,			\
+	"runtime procedure descriptor table exception information")	\
+_ELF_DEFINE_SHT(SHT_MIPS_ABIFLAGS,   0x7000002AUL,			\
+	"ABI flags")							\
+_ELF_DEFINE_SHT(SHT_SPARC_GOTDATA,   0x70000000UL,			\
+	"SPARC-specific data")						\
+_ELF_DEFINE_SHT(SHT_X86_64_UNWIND,   0x70000001UL,			\
+	"unwind tables for the AMD64")					\
+_ELF_DEFINE_SHT(SHT_ORDERED,         0x7FFFFFFFUL,			\
+	"sort entries in the section")					\
+_ELF_DEFINE_SHT(SHT_HIPROC,          0x7FFFFFFFUL,			\
+	"end of processor-specific range")				\
+_ELF_DEFINE_SHT(SHT_LOUSER,          0x80000000UL,			\
+	"start of application-specific range")				\
+_ELF_DEFINE_SHT(SHT_HIUSER,          0xFFFFFFFFUL,			\
+	"end of application-specific range")
+
+#undef	_ELF_DEFINE_SHT
+#define	_ELF_DEFINE_SHT(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_SECTION_TYPES()
+	SHT__LAST__ = SHT_HIUSER
+};
+
+/* Aliases for section types. */
+#define	SHT_AMD64_UNWIND	SHT_X86_64_UNWIND
+#define	SHT_GNU_verdef		SHT_SUNW_verdef
+#define	SHT_GNU_verneed		SHT_SUNW_verneed
+#define	SHT_GNU_versym		SHT_SUNW_versym
+
+/*
+ * Symbol binding information.
+ */
+
+#define	_ELF_DEFINE_SYMBOL_BINDING()					\
+_ELF_DEFINE_STB(STB_LOCAL,           0,					\
+	"not visible outside defining object file")			\
+_ELF_DEFINE_STB(STB_GLOBAL,          1,					\
+	"visible across all object files being combined")		\
+_ELF_DEFINE_STB(STB_WEAK,            2,					\
+	"visible across all object files but with low precedence")	\
+_ELF_DEFINE_STB(STB_LOOS,            10, "start of OS-specific range")	\
+_ELF_DEFINE_STB(STB_GNU_UNIQUE,      10, "unique symbol (GNU)")		\
+_ELF_DEFINE_STB(STB_HIOS,            12, "end of OS-specific range")	\
+_ELF_DEFINE_STB(STB_LOPROC,          13,				\
+	"start of processor-specific range")				\
+_ELF_DEFINE_STB(STB_HIPROC,          15,				\
+	"end of processor-specific range")
+
+#undef	_ELF_DEFINE_STB
+#define	_ELF_DEFINE_STB(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_SYMBOL_BINDING()
+	STB__LAST__
+};
+
+/*
+ * Symbol types
+ */
+
+#define	_ELF_DEFINE_SYMBOL_TYPES()					\
+_ELF_DEFINE_STT(STT_NOTYPE,          0, "unspecified type")		\
+_ELF_DEFINE_STT(STT_OBJECT,          1, "data object")			\
+_ELF_DEFINE_STT(STT_FUNC,            2, "executable code")		\
+_ELF_DEFINE_STT(STT_SECTION,         3, "section")			\
+_ELF_DEFINE_STT(STT_FILE,            4, "source file")			\
+_ELF_DEFINE_STT(STT_COMMON,          5, "uninitialized common block")	\
+_ELF_DEFINE_STT(STT_TLS,             6, "thread local storage")		\
+_ELF_DEFINE_STT(STT_LOOS,            10, "start of OS-specific types")	\
+_ELF_DEFINE_STT(STT_GNU_IFUNC,       10, "indirect function")	\
+_ELF_DEFINE_STT(STT_HIOS,            12, "end of OS-specific types")	\
+_ELF_DEFINE_STT(STT_LOPROC,          13,				\
+	"start of processor-specific types")				\
+_ELF_DEFINE_STT(STT_ARM_TFUNC,       13, "Thumb function (GNU)")	\
+_ELF_DEFINE_STT(STT_ARM_16BIT,       15, "Thumb label (GNU)")		\
+_ELF_DEFINE_STT(STT_SPARC_REGISTER,  13, "SPARC register information")	\
+_ELF_DEFINE_STT(STT_HIPROC,          15,				\
+	"end of processor-specific types")
+
+#undef	_ELF_DEFINE_STT
+#define	_ELF_DEFINE_STT(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_SYMBOL_TYPES()
+	STT__LAST__
+};
+
+/*
+ * Symbol binding.
+ */
+
+#define	_ELF_DEFINE_SYMBOL_BINDING_KINDS()		\
+_ELF_DEFINE_SYB(SYMINFO_BT_SELF,	0xFFFFU,	\
+	"bound to self")				\
+_ELF_DEFINE_SYB(SYMINFO_BT_PARENT,	0xFFFEU,	\
+	"bound to parent")				\
+_ELF_DEFINE_SYB(SYMINFO_BT_NONE,	0xFFFDU,	\
+	"no special binding")
+
+#undef	_ELF_DEFINE_SYB
+#define	_ELF_DEFINE_SYB(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_SYMBOL_BINDING_KINDS()
+	SYMINFO__LAST__
+};
+
+/*
+ * Symbol visibility.
+ */
+
+#define	_ELF_DEFINE_SYMBOL_VISIBILITY()		\
+_ELF_DEFINE_STV(STV_DEFAULT,         0,		\
+	"as specified by symbol type")		\
+_ELF_DEFINE_STV(STV_INTERNAL,        1,		\
+	"as defined by processor semantics")	\
+_ELF_DEFINE_STV(STV_HIDDEN,          2,		\
+	"hidden from other components")		\
+_ELF_DEFINE_STV(STV_PROTECTED,       3,		\
+	"local references are not preemptable")
+
+#undef	_ELF_DEFINE_STV
+#define	_ELF_DEFINE_STV(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_SYMBOL_VISIBILITY()
+	STV__LAST__
+};
+
+/*
+ * Symbol flags.
+ */
+#define	_ELF_DEFINE_SYMBOL_FLAGS()		\
+_ELF_DEFINE_SYF(SYMINFO_FLG_DIRECT,	0x01,	\
+	"directly assocated reference")		\
+_ELF_DEFINE_SYF(SYMINFO_FLG_COPY,	0x04,	\
+	"definition by copy-relocation")	\
+_ELF_DEFINE_SYF(SYMINFO_FLG_LAZYLOAD,	0x08,	\
+	"object should be lazily loaded")	\
+_ELF_DEFINE_SYF(SYMINFO_FLG_DIRECTBIND,	0x10,	\
+	"reference should be directly bound")	\
+_ELF_DEFINE_SYF(SYMINFO_FLG_NOEXTDIRECT, 0x20,	\
+	"external references not allowed to bind to definition")
+
+#undef	_ELF_DEFINE_SYF
+#define	_ELF_DEFINE_SYF(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_SYMBOL_FLAGS()
+	SYMINFO_FLG__LAST__
+};
+
+/*
+ * Version dependencies.
+ */
+#define	_ELF_DEFINE_VERSIONING_DEPENDENCIES()			\
+_ELF_DEFINE_VERD(VER_NDX_LOCAL,		0,	"local scope")	\
+_ELF_DEFINE_VERD(VER_NDX_GLOBAL,	1,	"global scope")
+#undef	_ELF_DEFINE_VERD
+#define	_ELF_DEFINE_VERD(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_VERSIONING_DEPENDENCIES()
+	VER_NDX__LAST__
+};
+
+/*
+ * Version flags.
+ */
+#define	_ELF_DEFINE_VERSIONING_FLAGS()				\
+_ELF_DEFINE_VERF(VER_FLG_BASE,		0x1,	"file version") \
+_ELF_DEFINE_VERF(VER_FLG_WEAK,		0x2,	"weak version")
+#undef	_ELF_DEFINE_VERF
+#define	_ELF_DEFINE_VERF(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_VERSIONING_FLAGS()
+	VER_FLG__LAST__
+};
+
+/*
+ * Version needs
+ */
+#define	_ELF_DEFINE_VERSIONING_NEEDS()					\
+_ELF_DEFINE_VRN(VER_NEED_NONE,		0,	"invalid version")	\
+_ELF_DEFINE_VRN(VER_NEED_CURRENT,	1,	"current version")
+#undef	_ELF_DEFINE_VRN
+#define	_ELF_DEFINE_VRN(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_VERSIONING_NEEDS()
+	VER_NEED__LAST__
+};
+
+/*
+ * Version numbers.
+ */
+#define	_ELF_DEFINE_VERSIONING_NUMBERS()				\
+_ELF_DEFINE_VRNU(VER_DEF_NONE,		0,	"invalid version")	\
+_ELF_DEFINE_VRNU(VER_DEF_CURRENT,	1, 	"current version")
+#undef	_ELF_DEFINE_VRNU
+#define	_ELF_DEFINE_VRNU(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_VERSIONING_NUMBERS()
+	VER_DEF__LAST__
+};
+
+/**
+ ** Relocation types.
+ **/
+
+#define	_ELF_DEFINE_386_RELOCATIONS()		\
+_ELF_DEFINE_RELOC(R_386_NONE,		0)	\
+_ELF_DEFINE_RELOC(R_386_32,		1)	\
+_ELF_DEFINE_RELOC(R_386_PC32,		2)	\
+_ELF_DEFINE_RELOC(R_386_GOT32,		3)	\
+_ELF_DEFINE_RELOC(R_386_PLT32,		4)	\
+_ELF_DEFINE_RELOC(R_386_COPY,		5)	\
+_ELF_DEFINE_RELOC(R_386_GLOB_DAT,	6)	\
+_ELF_DEFINE_RELOC(R_386_JUMP_SLOT,	7)	\
+_ELF_DEFINE_RELOC(R_386_RELATIVE,	8)	\
+_ELF_DEFINE_RELOC(R_386_GOTOFF,		9)	\
+_ELF_DEFINE_RELOC(R_386_GOTPC,		10)	\
+_ELF_DEFINE_RELOC(R_386_32PLT,		11)	\
+_ELF_DEFINE_RELOC(R_386_TLS_TPOFF,	14)	\
+_ELF_DEFINE_RELOC(R_386_TLS_IE,		15)	\
+_ELF_DEFINE_RELOC(R_386_TLS_GOTIE,	16)	\
+_ELF_DEFINE_RELOC(R_386_TLS_LE,		17)	\
+_ELF_DEFINE_RELOC(R_386_TLS_GD,		18)	\
+_ELF_DEFINE_RELOC(R_386_TLS_LDM,	19)	\
+_ELF_DEFINE_RELOC(R_386_16,		20)	\
+_ELF_DEFINE_RELOC(R_386_PC16,		21)	\
+_ELF_DEFINE_RELOC(R_386_8,		22)	\
+_ELF_DEFINE_RELOC(R_386_PC8,		23)	\
+_ELF_DEFINE_RELOC(R_386_TLS_GD_32,	24)	\
+_ELF_DEFINE_RELOC(R_386_TLS_GD_PUSH,	25)	\
+_ELF_DEFINE_RELOC(R_386_TLS_GD_CALL,	26)	\
+_ELF_DEFINE_RELOC(R_386_TLS_GD_POP,	27)	\
+_ELF_DEFINE_RELOC(R_386_TLS_LDM_32,	28)	\
+_ELF_DEFINE_RELOC(R_386_TLS_LDM_PUSH,	29)	\
+_ELF_DEFINE_RELOC(R_386_TLS_LDM_CALL,	30)	\
+_ELF_DEFINE_RELOC(R_386_TLS_LDM_POP,	31)	\
+_ELF_DEFINE_RELOC(R_386_TLS_LDO_32,	32)	\
+_ELF_DEFINE_RELOC(R_386_TLS_IE_32,	33)	\
+_ELF_DEFINE_RELOC(R_386_TLS_LE_32,	34)	\
+_ELF_DEFINE_RELOC(R_386_TLS_DTPMOD32,	35)	\
+_ELF_DEFINE_RELOC(R_386_TLS_DTPOFF32,	36)	\
+_ELF_DEFINE_RELOC(R_386_TLS_TPOFF32,	37)	\
+_ELF_DEFINE_RELOC(R_386_SIZE32,		38)	\
+_ELF_DEFINE_RELOC(R_386_TLS_GOTDESC,	39)	\
+_ELF_DEFINE_RELOC(R_386_TLS_DESC_CALL,	40)	\
+_ELF_DEFINE_RELOC(R_386_TLS_DESC,	41)	\
+_ELF_DEFINE_RELOC(R_386_IRELATIVE,	42)	\
+_ELF_DEFINE_RELOC(R_386_GOT32X,		43)
+
+
+/*
+ */
+#define	_ELF_DEFINE_AARCH64_RELOCATIONS()				\
+_ELF_DEFINE_RELOC(R_AARCH64_NONE,				0)	\
+_ELF_DEFINE_RELOC(R_AARCH64_ABS64,				257)	\
+_ELF_DEFINE_RELOC(R_AARCH64_ABS32,				258)	\
+_ELF_DEFINE_RELOC(R_AARCH64_ABS16,				259)	\
+_ELF_DEFINE_RELOC(R_AARCH64_PREL64,				260)	\
+_ELF_DEFINE_RELOC(R_AARCH64_PREL32,				261)	\
+_ELF_DEFINE_RELOC(R_AARCH64_PREL16,				262)	\
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G0,			263)	\
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G0_NC,			264)	\
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G1,			265)	\
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G1_NC,			266)	\
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G2,			267)	\
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G2_NC,			268)	\
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G3,			269)	\
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_SABS_G0,			270)	\
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_SABS_G1,			271)	\
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_SABS_G2,			272)	\
+_ELF_DEFINE_RELOC(R_AARCH64_LD_PREL_LO19,			273)	\
+_ELF_DEFINE_RELOC(R_AARCH64_ADR_PREL_LO21,			274)	\
+_ELF_DEFINE_RELOC(R_AARCH64_ADR_PREL_PG_HI21,			275)	\
+_ELF_DEFINE_RELOC(R_AARCH64_ADR_PREL_PG_HI21_NC,		276)	\
+_ELF_DEFINE_RELOC(R_AARCH64_ADD_ABS_LO12_NC,			277)	\
+_ELF_DEFINE_RELOC(R_AARCH64_LDST8_ABS_LO12_NC,			278)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TSTBR14,				279)	\
+_ELF_DEFINE_RELOC(R_AARCH64_CONDBR19,				280)	\
+_ELF_DEFINE_RELOC(R_AARCH64_JUMP26,				282)	\
+_ELF_DEFINE_RELOC(R_AARCH64_CALL26,				283)	\
+_ELF_DEFINE_RELOC(R_AARCH64_LDST16_ABS_LO12_NC,			284)	\
+_ELF_DEFINE_RELOC(R_AARCH64_LDST32_ABS_LO12_NC,			285)	\
+_ELF_DEFINE_RELOC(R_AARCH64_LDST64_ABS_LO12_NC,			286)	\
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G0,			287)	\
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G0_NC,			288)	\
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G1,			289)	\
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G1_NC,			290)	\
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G2,			291)	\
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G2_NC,			292)	\
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G3,			293)	\
+_ELF_DEFINE_RELOC(R_AARCH64_LDST128_ABS_LO12_NC,		299)	\
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G0,			300)	\
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G0_NC,			301)	\
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G1,			302)	\
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G1_NC,			303)	\
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G2,			304)	\
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G2_NC,			305)	\
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G3,			306)	\
+_ELF_DEFINE_RELOC(R_AARCH64_GOTREL64,				307)	\
+_ELF_DEFINE_RELOC(R_AARCH64_GOTREL32,				308)	\
+_ELF_DEFINE_RELOC(R_AARCH64_GOT_LD_PREL19,			309)	\
+_ELF_DEFINE_RELOC(R_AARCH64_LD64_GOTOFF_LO15,			310)	\
+_ELF_DEFINE_RELOC(R_AARCH64_ADR_GOT_PAGE,			311)	\
+_ELF_DEFINE_RELOC(R_AARCH64_LD64_GOT_LO12_NC,			312)	\
+_ELF_DEFINE_RELOC(R_AARCH64_LD64_GOTPAGE_LO15,			313)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSGD_ADR_PREL21,			512)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSGD_ADR_PAGE21,			513)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSGD_ADD_LO12_NC,			514)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSGD_MOVW_G1,			515)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSGD_MOVW_G0_NC,			516)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_ADR_PREL21,			517)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_ADR_PAGE21,			518)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_ADD_LO12_NC,			519)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_G1,			520)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_G0_NC,			521)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LD_PREL19,			522)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G2,		523)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G1,		524)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC,		525)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G0,		526)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC,		527)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_HI12,		529)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC,		530)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST8_DTPREL_LO12,		531)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC,		532)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST16_DTPREL_LO12,		533)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,	534)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST32_DTPREL_LO12,		535)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,	536)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST64_DTPREL_LO12,		537)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC,	538)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSIE_MOVW_GOTTPREL_G1,		539)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC,		540)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21,		541)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC,	542)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSIE_LD_GOTTPREL_PREL19,		543)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G2,		544)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G1,		545)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G1_NC,		546)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G0,		547)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G0_NC,		548)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_ADD_TPREL_HI12,		549)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_ADD_TPREL_LO12,		550)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_ADD_TPREL_LO12_NC,		551)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST8_TPREL_LO12,		552)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC,		553)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST16_TPREL_LO12,		554)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC,		555)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST32_TPREL_LO12,		556)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC,		557)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST64_TPREL_LO12,		558)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC,		559)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_LD_PREL19,			560)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_ADR_PREL21,			561)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_ADR_PAGE21,			562)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_LD64_LO12,			563)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_ADD_LO12,			564)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_OFF_G1,			565)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_OFF_G0_NC,			566)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_LDR,			567)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_ADD,			568)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_CALL,			569)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST128_TPREL_LO12,		570)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC,	571)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST128_DTPREL_LO12,		572)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC,	573)	\
+_ELF_DEFINE_RELOC(R_AARCH64_COPY,				1024)	\
+_ELF_DEFINE_RELOC(R_AARCH64_GLOB_DAT,				1025)	\
+_ELF_DEFINE_RELOC(R_AARCH64_JUMP_SLOT,				1026)	\
+_ELF_DEFINE_RELOC(R_AARCH64_RELATIVE,				1027)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLS_DTPREL64,			1028)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLS_DTPMOD64,			1029)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLS_TPREL64,			1030)	\
+_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC,				1031)	\
+_ELF_DEFINE_RELOC(R_AARCH64_IRELATIVE,				1032)
+
+/*
+ * These are the symbols used in the Sun ``Linkers and Loaders
+ * Guide'', Document No: 817-1984-17.  See the X86_64 relocations list
+ * below for the spellings used in the ELF specification.
+ */
+#define	_ELF_DEFINE_AMD64_RELOCATIONS()		\
+_ELF_DEFINE_RELOC(R_AMD64_NONE,		0)	\
+_ELF_DEFINE_RELOC(R_AMD64_64,		1)	\
+_ELF_DEFINE_RELOC(R_AMD64_PC32,		2)	\
+_ELF_DEFINE_RELOC(R_AMD64_GOT32,	3)	\
+_ELF_DEFINE_RELOC(R_AMD64_PLT32,	4)	\
+_ELF_DEFINE_RELOC(R_AMD64_COPY,		5)	\
+_ELF_DEFINE_RELOC(R_AMD64_GLOB_DAT,	6)	\
+_ELF_DEFINE_RELOC(R_AMD64_JUMP_SLOT,	7)	\
+_ELF_DEFINE_RELOC(R_AMD64_RELATIVE,	8)	\
+_ELF_DEFINE_RELOC(R_AMD64_GOTPCREL,	9)	\
+_ELF_DEFINE_RELOC(R_AMD64_32,		10)	\
+_ELF_DEFINE_RELOC(R_AMD64_32S,		11)	\
+_ELF_DEFINE_RELOC(R_AMD64_16,		12)	\
+_ELF_DEFINE_RELOC(R_AMD64_PC16,		13)	\
+_ELF_DEFINE_RELOC(R_AMD64_8,		14)	\
+_ELF_DEFINE_RELOC(R_AMD64_PC8,		15)	\
+_ELF_DEFINE_RELOC(R_AMD64_PC64,		24)	\
+_ELF_DEFINE_RELOC(R_AMD64_GOTOFF64,	25)	\
+_ELF_DEFINE_RELOC(R_AMD64_GOTPC32,	26)
+
+/*
+ * Relocation definitions from the ARM ELF ABI, version "ARM IHI
+ * 0044E" released on 30th November 2012.
+ */
+#define	_ELF_DEFINE_ARM_RELOCATIONS()			\
+_ELF_DEFINE_RELOC(R_ARM_NONE,			0)	\
+_ELF_DEFINE_RELOC(R_ARM_PC24,			1)	\
+_ELF_DEFINE_RELOC(R_ARM_ABS32,			2)	\
+_ELF_DEFINE_RELOC(R_ARM_REL32,			3)	\
+_ELF_DEFINE_RELOC(R_ARM_LDR_PC_G0,		4)	\
+_ELF_DEFINE_RELOC(R_ARM_ABS16,			5)	\
+_ELF_DEFINE_RELOC(R_ARM_ABS12,			6)	\
+_ELF_DEFINE_RELOC(R_ARM_THM_ABS5,		7)	\
+_ELF_DEFINE_RELOC(R_ARM_ABS8,			8)	\
+_ELF_DEFINE_RELOC(R_ARM_SBREL32,		9)	\
+_ELF_DEFINE_RELOC(R_ARM_THM_CALL,		10)	\
+_ELF_DEFINE_RELOC(R_ARM_THM_PC8,		11)	\
+_ELF_DEFINE_RELOC(R_ARM_BREL_ADJ,		12)	\
+_ELF_DEFINE_RELOC(R_ARM_SWI24,			13)	\
+_ELF_DEFINE_RELOC(R_ARM_TLS_DESC,		13)	\
+_ELF_DEFINE_RELOC(R_ARM_THM_SWI8,		14)	\
+_ELF_DEFINE_RELOC(R_ARM_XPC25,			15)	\
+_ELF_DEFINE_RELOC(R_ARM_THM_XPC22,		16)	\
+_ELF_DEFINE_RELOC(R_ARM_TLS_DTPMOD32,		17)	\
+_ELF_DEFINE_RELOC(R_ARM_TLS_DTPOFF32,		18)	\
+_ELF_DEFINE_RELOC(R_ARM_TLS_TPOFF32,		19)	\
+_ELF_DEFINE_RELOC(R_ARM_COPY,			20)	\
+_ELF_DEFINE_RELOC(R_ARM_GLOB_DAT,		21)	\
+_ELF_DEFINE_RELOC(R_ARM_JUMP_SLOT,		22)	\
+_ELF_DEFINE_RELOC(R_ARM_RELATIVE,		23)	\
+_ELF_DEFINE_RELOC(R_ARM_GOTOFF32,		24)	\
+_ELF_DEFINE_RELOC(R_ARM_BASE_PREL,		25)	\
+_ELF_DEFINE_RELOC(R_ARM_GOT_BREL,		26)	\
+_ELF_DEFINE_RELOC(R_ARM_PLT32,			27)	\
+_ELF_DEFINE_RELOC(R_ARM_CALL,			28)	\
+_ELF_DEFINE_RELOC(R_ARM_JUMP24,			29)	\
+_ELF_DEFINE_RELOC(R_ARM_THM_JUMP24,		30)	\
+_ELF_DEFINE_RELOC(R_ARM_BASE_ABS,		31)	\
+_ELF_DEFINE_RELOC(R_ARM_ALU_PCREL_7_0,		32)	\
+_ELF_DEFINE_RELOC(R_ARM_ALU_PCREL_15_8,		33)	\
+_ELF_DEFINE_RELOC(R_ARM_ALU_PCREL_23_15,	34)	\
+_ELF_DEFINE_RELOC(R_ARM_LDR_SBREL_11_0_NC,	35)	\
+_ELF_DEFINE_RELOC(R_ARM_ALU_SBREL_19_12_NC,	36)	\
+_ELF_DEFINE_RELOC(R_ARM_ALU_SBREL_27_20_CK,	37)	\
+_ELF_DEFINE_RELOC(R_ARM_TARGET1,		38)	\
+_ELF_DEFINE_RELOC(R_ARM_SBREL31,		39)	\
+_ELF_DEFINE_RELOC(R_ARM_V4BX,			40)	\
+_ELF_DEFINE_RELOC(R_ARM_TARGET2,		41)	\
+_ELF_DEFINE_RELOC(R_ARM_PREL31,			42)	\
+_ELF_DEFINE_RELOC(R_ARM_MOVW_ABS_NC,		43)	\
+_ELF_DEFINE_RELOC(R_ARM_MOVT_ABS,		44)	\
+_ELF_DEFINE_RELOC(R_ARM_MOVW_PREL_NC,		45)	\
+_ELF_DEFINE_RELOC(R_ARM_MOVT_PREL,		46)	\
+_ELF_DEFINE_RELOC(R_ARM_THM_MOVW_ABS_NC,	47)	\
+_ELF_DEFINE_RELOC(R_ARM_THM_MOVT_ABS,		48)	\
+_ELF_DEFINE_RELOC(R_ARM_THM_MOVW_PREL_NC,	49)	\
+_ELF_DEFINE_RELOC(R_ARM_THM_MOVT_PREL,		50)	\
+_ELF_DEFINE_RELOC(R_ARM_THM_JUMP19,		51)	\
+_ELF_DEFINE_RELOC(R_ARM_THM_JUMP6,		52)	\
+_ELF_DEFINE_RELOC(R_ARM_THM_ALU_PREL_11_0,	53)	\
+_ELF_DEFINE_RELOC(R_ARM_THM_PC12,		54)	\
+_ELF_DEFINE_RELOC(R_ARM_ABS32_NOI,		55)	\
+_ELF_DEFINE_RELOC(R_ARM_REL32_NOI,		56)	\
+_ELF_DEFINE_RELOC(R_ARM_ALU_PC_G0_NC,		57)	\
+_ELF_DEFINE_RELOC(R_ARM_ALU_PC_G0,		58)	\
+_ELF_DEFINE_RELOC(R_ARM_ALU_PC_G1_NC,		59)	\
+_ELF_DEFINE_RELOC(R_ARM_ALU_PC_G1,		60)	\
+_ELF_DEFINE_RELOC(R_ARM_ALU_PC_G2,		61)	\
+_ELF_DEFINE_RELOC(R_ARM_LDR_PC_G1,		62)	\
+_ELF_DEFINE_RELOC(R_ARM_LDR_PC_G2,		63)	\
+_ELF_DEFINE_RELOC(R_ARM_LDRS_PC_G0,		64)	\
+_ELF_DEFINE_RELOC(R_ARM_LDRS_PC_G1,		65)	\
+_ELF_DEFINE_RELOC(R_ARM_LDRS_PC_G2,		66)	\
+_ELF_DEFINE_RELOC(R_ARM_LDC_PC_G0,		67)	\
+_ELF_DEFINE_RELOC(R_ARM_LDC_PC_G1,		68)	\
+_ELF_DEFINE_RELOC(R_ARM_LDC_PC_G2,		69)	\
+_ELF_DEFINE_RELOC(R_ARM_ALU_SB_G0_NC,		70)	\
+_ELF_DEFINE_RELOC(R_ARM_ALU_SB_G0,		71)	\
+_ELF_DEFINE_RELOC(R_ARM_ALU_SB_G1_NC,		72)	\
+_ELF_DEFINE_RELOC(R_ARM_ALU_SB_G1,		73)	\
+_ELF_DEFINE_RELOC(R_ARM_ALU_SB_G2,		74)	\
+_ELF_DEFINE_RELOC(R_ARM_LDR_SB_G0,		75)	\
+_ELF_DEFINE_RELOC(R_ARM_LDR_SB_G1,		76)	\
+_ELF_DEFINE_RELOC(R_ARM_LDR_SB_G2,		77)	\
+_ELF_DEFINE_RELOC(R_ARM_LDRS_SB_G0,		78)	\
+_ELF_DEFINE_RELOC(R_ARM_LDRS_SB_G1,		79)	\
+_ELF_DEFINE_RELOC(R_ARM_LDRS_SB_G2,		80)	\
+_ELF_DEFINE_RELOC(R_ARM_LDC_SB_G0,		81)	\
+_ELF_DEFINE_RELOC(R_ARM_LDC_SB_G1,		82)	\
+_ELF_DEFINE_RELOC(R_ARM_LDC_SB_G2,		83)	\
+_ELF_DEFINE_RELOC(R_ARM_MOVW_BREL_NC,		84)	\
+_ELF_DEFINE_RELOC(R_ARM_MOVT_BREL,		85)	\
+_ELF_DEFINE_RELOC(R_ARM_MOVW_BREL,		86)	\
+_ELF_DEFINE_RELOC(R_ARM_THM_MOVW_BREL_NC,	87)	\
+_ELF_DEFINE_RELOC(R_ARM_THM_MOVT_BREL,		88)	\
+_ELF_DEFINE_RELOC(R_ARM_THM_MOVW_BREL,		89)	\
+_ELF_DEFINE_RELOC(R_ARM_TLS_GOTDESC,		90)	\
+_ELF_DEFINE_RELOC(R_ARM_TLS_CALL,		91)	\
+_ELF_DEFINE_RELOC(R_ARM_TLS_DESCSEQ,		92)	\
+_ELF_DEFINE_RELOC(R_ARM_THM_TLS_CALL,		93)	\
+_ELF_DEFINE_RELOC(R_ARM_PLT32_ABS,		94)	\
+_ELF_DEFINE_RELOC(R_ARM_GOT_ABS,		95)	\
+_ELF_DEFINE_RELOC(R_ARM_GOT_PREL,		96)	\
+_ELF_DEFINE_RELOC(R_ARM_GOT_BREL12,		97)	\
+_ELF_DEFINE_RELOC(R_ARM_GOTOFF12,		98)	\
+_ELF_DEFINE_RELOC(R_ARM_GOTRELAX,		99)	\
+_ELF_DEFINE_RELOC(R_ARM_GNU_VTENTRY,		100)	\
+_ELF_DEFINE_RELOC(R_ARM_GNU_VTINHERIT,		101)	\
+_ELF_DEFINE_RELOC(R_ARM_THM_JUMP11,		102)	\
+_ELF_DEFINE_RELOC(R_ARM_THM_JUMP8,		103)	\
+_ELF_DEFINE_RELOC(R_ARM_TLS_GD32,		104)	\
+_ELF_DEFINE_RELOC(R_ARM_TLS_LDM32,		105)	\
+_ELF_DEFINE_RELOC(R_ARM_TLS_LDO32,		106)	\
+_ELF_DEFINE_RELOC(R_ARM_TLS_IE32,		107)	\
+_ELF_DEFINE_RELOC(R_ARM_TLS_LE32,		108)	\
+_ELF_DEFINE_RELOC(R_ARM_TLS_LDO12,		109)	\
+_ELF_DEFINE_RELOC(R_ARM_TLS_LE12,		110)	\
+_ELF_DEFINE_RELOC(R_ARM_TLS_IE12GP,		111)	\
+_ELF_DEFINE_RELOC(R_ARM_PRIVATE_0,		112)	\
+_ELF_DEFINE_RELOC(R_ARM_PRIVATE_1,		113)	\
+_ELF_DEFINE_RELOC(R_ARM_PRIVATE_2,		114)	\
+_ELF_DEFINE_RELOC(R_ARM_PRIVATE_3,		115)	\
+_ELF_DEFINE_RELOC(R_ARM_PRIVATE_4,		116)	\
+_ELF_DEFINE_RELOC(R_ARM_PRIVATE_5,		117)	\
+_ELF_DEFINE_RELOC(R_ARM_PRIVATE_6,		118)	\
+_ELF_DEFINE_RELOC(R_ARM_PRIVATE_7,		119)	\
+_ELF_DEFINE_RELOC(R_ARM_PRIVATE_8,		120)	\
+_ELF_DEFINE_RELOC(R_ARM_PRIVATE_9,		121)	\
+_ELF_DEFINE_RELOC(R_ARM_PRIVATE_10,		122)	\
+_ELF_DEFINE_RELOC(R_ARM_PRIVATE_11,		123)	\
+_ELF_DEFINE_RELOC(R_ARM_PRIVATE_12,		124)	\
+_ELF_DEFINE_RELOC(R_ARM_PRIVATE_13,		125)	\
+_ELF_DEFINE_RELOC(R_ARM_PRIVATE_14,		126)	\
+_ELF_DEFINE_RELOC(R_ARM_PRIVATE_15,		127)	\
+_ELF_DEFINE_RELOC(R_ARM_ME_TOO,			128)	\
+_ELF_DEFINE_RELOC(R_ARM_THM_TLS_DESCSEQ16,	129)	\
+_ELF_DEFINE_RELOC(R_ARM_THM_TLS_DESCSEQ32,	130)	\
+_ELF_DEFINE_RELOC(R_ARM_THM_GOT_BREL12,		131)	\
+_ELF_DEFINE_RELOC(R_ARM_IRELATIVE,		140)
+
+#define	_ELF_DEFINE_IA64_RELOCATIONS()			\
+_ELF_DEFINE_RELOC(R_IA_64_NONE,			0)	\
+_ELF_DEFINE_RELOC(R_IA_64_IMM14,		0x21)	\
+_ELF_DEFINE_RELOC(R_IA_64_IMM22,		0x22)	\
+_ELF_DEFINE_RELOC(R_IA_64_IMM64,		0x23)	\
+_ELF_DEFINE_RELOC(R_IA_64_DIR32MSB,		0x24)	\
+_ELF_DEFINE_RELOC(R_IA_64_DIR32LSB,		0x25)	\
+_ELF_DEFINE_RELOC(R_IA_64_DIR64MSB,		0x26)	\
+_ELF_DEFINE_RELOC(R_IA_64_DIR64LSB,		0x27)	\
+_ELF_DEFINE_RELOC(R_IA_64_GPREL22,		0x2a)	\
+_ELF_DEFINE_RELOC(R_IA_64_GPREL64I,		0x2b)	\
+_ELF_DEFINE_RELOC(R_IA_64_GPREL32MSB,		0x2c)	\
+_ELF_DEFINE_RELOC(R_IA_64_GPREL32LSB,		0x2d)	\
+_ELF_DEFINE_RELOC(R_IA_64_GPREL64MSB,		0x2e)	\
+_ELF_DEFINE_RELOC(R_IA_64_GPREL64LSB,		0x2f)	\
+_ELF_DEFINE_RELOC(R_IA_64_LTOFF22,		0x32)	\
+_ELF_DEFINE_RELOC(R_IA_64_LTOFF64I,		0x33)	\
+_ELF_DEFINE_RELOC(R_IA_64_PLTOFF22,		0x3a)	\
+_ELF_DEFINE_RELOC(R_IA_64_PLTOFF64I,		0x3b)	\
+_ELF_DEFINE_RELOC(R_IA_64_PLTOFF64MSB,		0x3e)	\
+_ELF_DEFINE_RELOC(R_IA_64_PLTOFF64LSB,		0x3f)	\
+_ELF_DEFINE_RELOC(R_IA_64_FPTR64I,		0x43)	\
+_ELF_DEFINE_RELOC(R_IA_64_FPTR32MSB,		0x44)	\
+_ELF_DEFINE_RELOC(R_IA_64_FPTR32LSB,		0x45)	\
+_ELF_DEFINE_RELOC(R_IA_64_FPTR64MSB,		0x46)	\
+_ELF_DEFINE_RELOC(R_IA_64_FPTR64LSB,		0x47)	\
+_ELF_DEFINE_RELOC(R_IA_64_PCREL60B,		0x48)	\
+_ELF_DEFINE_RELOC(R_IA_64_PCREL21B,		0x49)	\
+_ELF_DEFINE_RELOC(R_IA_64_PCREL21M,		0x4a)	\
+_ELF_DEFINE_RELOC(R_IA_64_PCREL21F,		0x4b)	\
+_ELF_DEFINE_RELOC(R_IA_64_PCREL32MSB,		0x4c)	\
+_ELF_DEFINE_RELOC(R_IA_64_PCREL32LSB,		0x4d)	\
+_ELF_DEFINE_RELOC(R_IA_64_PCREL64MSB,		0x4e)	\
+_ELF_DEFINE_RELOC(R_IA_64_PCREL64LSB,		0x4f)	\
+_ELF_DEFINE_RELOC(R_IA_64_LTOFF_FPTR22,		0x52)	\
+_ELF_DEFINE_RELOC(R_IA_64_LTOFF_FPTR64I,	0x53)	\
+_ELF_DEFINE_RELOC(R_IA_64_LTOFF_FPTR32MSB,	0x54)	\
+_ELF_DEFINE_RELOC(R_IA_64_LTOFF_FPTR32LSB,	0x55)	\
+_ELF_DEFINE_RELOC(R_IA_64_LTOFF_FPTR64MSB,	0x56)	\
+_ELF_DEFINE_RELOC(R_IA_64_LTOFF_FPTR64LSB,	0x57)	\
+_ELF_DEFINE_RELOC(R_IA_64_SEGREL32MSB,		0x5c)	\
+_ELF_DEFINE_RELOC(R_IA_64_SEGREL32LSB,		0x5d)	\
+_ELF_DEFINE_RELOC(R_IA_64_SEGREL64MSB,		0x5e)	\
+_ELF_DEFINE_RELOC(R_IA_64_SEGREL64LSB,		0x5f)	\
+_ELF_DEFINE_RELOC(R_IA_64_SECREL32MSB,		0x64)	\
+_ELF_DEFINE_RELOC(R_IA_64_SECREL32LSB,		0x65)	\
+_ELF_DEFINE_RELOC(R_IA_64_SECREL64MSB,		0x66)	\
+_ELF_DEFINE_RELOC(R_IA_64_SECREL64LSB,		0x67)	\
+_ELF_DEFINE_RELOC(R_IA_64_REL32MSB,		0x6c)	\
+_ELF_DEFINE_RELOC(R_IA_64_REL32LSB,		0x6d)	\
+_ELF_DEFINE_RELOC(R_IA_64_REL64MSB,		0x6e)	\
+_ELF_DEFINE_RELOC(R_IA_64_REL64LSB,		0x6f)	\
+_ELF_DEFINE_RELOC(R_IA_64_LTV32MSB,		0x74)	\
+_ELF_DEFINE_RELOC(R_IA_64_LTV32LSB,		0x75)	\
+_ELF_DEFINE_RELOC(R_IA_64_LTV64MSB,		0x76)	\
+_ELF_DEFINE_RELOC(R_IA_64_LTV64LSB,		0x77)	\
+_ELF_DEFINE_RELOC(R_IA_64_PCREL21BI,		0x79)	\
+_ELF_DEFINE_RELOC(R_IA_64_PCREL22,		0x7A)	\
+_ELF_DEFINE_RELOC(R_IA_64_PCREL64I,		0x7B)	\
+_ELF_DEFINE_RELOC(R_IA_64_IPLTMSB,		0x80)	\
+_ELF_DEFINE_RELOC(R_IA_64_IPLTLSB,		0x81)	\
+_ELF_DEFINE_RELOC(R_IA_64_SUB,			0x85)	\
+_ELF_DEFINE_RELOC(R_IA_64_LTOFF22X,		0x86)	\
+_ELF_DEFINE_RELOC(R_IA_64_LDXMOV,		0x87)	\
+_ELF_DEFINE_RELOC(R_IA_64_TPREL14,		0x91)	\
+_ELF_DEFINE_RELOC(R_IA_64_TPREL22,		0x92)	\
+_ELF_DEFINE_RELOC(R_IA_64_TPREL64I,		0x93)	\
+_ELF_DEFINE_RELOC(R_IA_64_TPREL64MSB,		0x96)	\
+_ELF_DEFINE_RELOC(R_IA_64_TPREL64LSB,		0x97)	\
+_ELF_DEFINE_RELOC(R_IA_64_LTOFF_TPREL22,	0x9A)	\
+_ELF_DEFINE_RELOC(R_IA_64_DTPMOD64MSB,		0xA6)	\
+_ELF_DEFINE_RELOC(R_IA_64_DTPMOD64LSB,		0xA7)	\
+_ELF_DEFINE_RELOC(R_IA_64_LTOFF_DTPMOD22,	0xAA)	\
+_ELF_DEFINE_RELOC(R_IA_64_DTPREL14,		0xB1)	\
+_ELF_DEFINE_RELOC(R_IA_64_DTPREL22,		0xB2)	\
+_ELF_DEFINE_RELOC(R_IA_64_DTPREL64I,		0xB3)	\
+_ELF_DEFINE_RELOC(R_IA_64_DTPREL32MSB,		0xB4)	\
+_ELF_DEFINE_RELOC(R_IA_64_DTPREL32LSB,		0xB5)	\
+_ELF_DEFINE_RELOC(R_IA_64_DTPREL64MSB,		0xB6)	\
+_ELF_DEFINE_RELOC(R_IA_64_DTPREL64LSB,		0xB7)	\
+_ELF_DEFINE_RELOC(R_IA_64_LTOFF_DTPREL22,	0xBA)
+
+#define	_ELF_DEFINE_MIPS_RELOCATIONS()			\
+_ELF_DEFINE_RELOC(R_MIPS_NONE,			0)	\
+_ELF_DEFINE_RELOC(R_MIPS_16,			1)	\
+_ELF_DEFINE_RELOC(R_MIPS_32,			2)	\
+_ELF_DEFINE_RELOC(R_MIPS_REL32,			3)	\
+_ELF_DEFINE_RELOC(R_MIPS_26,			4)	\
+_ELF_DEFINE_RELOC(R_MIPS_HI16,			5)	\
+_ELF_DEFINE_RELOC(R_MIPS_LO16,			6)	\
+_ELF_DEFINE_RELOC(R_MIPS_GPREL16,		7)	\
+_ELF_DEFINE_RELOC(R_MIPS_LITERAL, 		8)	\
+_ELF_DEFINE_RELOC(R_MIPS_GOT16,			9)	\
+_ELF_DEFINE_RELOC(R_MIPS_PC16,			10)	\
+_ELF_DEFINE_RELOC(R_MIPS_CALL16,		11)	\
+_ELF_DEFINE_RELOC(R_MIPS_GPREL32,		12)	\
+_ELF_DEFINE_RELOC(R_MIPS_SHIFT5,		16)	\
+_ELF_DEFINE_RELOC(R_MIPS_SHIFT6,		17)	\
+_ELF_DEFINE_RELOC(R_MIPS_64,			18)	\
+_ELF_DEFINE_RELOC(R_MIPS_GOT_DISP,		19)	\
+_ELF_DEFINE_RELOC(R_MIPS_GOT_PAGE,		20)	\
+_ELF_DEFINE_RELOC(R_MIPS_GOT_OFST,		21)	\
+_ELF_DEFINE_RELOC(R_MIPS_GOT_HI16,		22)	\
+_ELF_DEFINE_RELOC(R_MIPS_GOT_LO16,		23)	\
+_ELF_DEFINE_RELOC(R_MIPS_SUB,			24)	\
+_ELF_DEFINE_RELOC(R_MIPS_CALLHI16,		30)	\
+_ELF_DEFINE_RELOC(R_MIPS_CALLLO16,		31)	\
+_ELF_DEFINE_RELOC(R_MIPS_JALR,			37)	\
+_ELF_DEFINE_RELOC(R_MIPS_TLS_DTPMOD32,		38)	\
+_ELF_DEFINE_RELOC(R_MIPS_TLS_DTPREL32,		39)	\
+_ELF_DEFINE_RELOC(R_MIPS_TLS_DTPMOD64,		40)	\
+_ELF_DEFINE_RELOC(R_MIPS_TLS_DTPREL64,		41)	\
+_ELF_DEFINE_RELOC(R_MIPS_TLS_GD,		42)	\
+_ELF_DEFINE_RELOC(R_MIPS_TLS_LDM,		43)	\
+_ELF_DEFINE_RELOC(R_MIPS_TLS_DTPREL_HI16,	44)	\
+_ELF_DEFINE_RELOC(R_MIPS_TLS_DTPREL_LO16,	45)	\
+_ELF_DEFINE_RELOC(R_MIPS_TLS_GOTTPREL,		46)	\
+_ELF_DEFINE_RELOC(R_MIPS_TLS_TPREL32,		47)	\
+_ELF_DEFINE_RELOC(R_MIPS_TLS_TPREL64,		48)	\
+_ELF_DEFINE_RELOC(R_MIPS_TLS_TPREL_HI16,	49)	\
+_ELF_DEFINE_RELOC(R_MIPS_TLS_TPREL_LO16,	50)
+
+#define	_ELF_DEFINE_PPC32_RELOCATIONS()		\
+_ELF_DEFINE_RELOC(R_PPC_NONE,		0)	\
+_ELF_DEFINE_RELOC(R_PPC_ADDR32,		1)	\
+_ELF_DEFINE_RELOC(R_PPC_ADDR24,		2)	\
+_ELF_DEFINE_RELOC(R_PPC_ADDR16,		3)	\
+_ELF_DEFINE_RELOC(R_PPC_ADDR16_LO,	4)	\
+_ELF_DEFINE_RELOC(R_PPC_ADDR16_HI,	5)	\
+_ELF_DEFINE_RELOC(R_PPC_ADDR16_HA,	6)	\
+_ELF_DEFINE_RELOC(R_PPC_ADDR14,		7)	\
+_ELF_DEFINE_RELOC(R_PPC_ADDR14_BRTAKEN,	8)	\
+_ELF_DEFINE_RELOC(R_PPC_ADDR14_BRNTAKEN, 9)	\
+_ELF_DEFINE_RELOC(R_PPC_REL24,		10)	\
+_ELF_DEFINE_RELOC(R_PPC_REL14,		11)	\
+_ELF_DEFINE_RELOC(R_PPC_REL14_BRTAKEN,	12)	\
+_ELF_DEFINE_RELOC(R_PPC_REL14_BRNTAKEN,	13)	\
+_ELF_DEFINE_RELOC(R_PPC_GOT16,		14)	\
+_ELF_DEFINE_RELOC(R_PPC_GOT16_LO,	15)	\
+_ELF_DEFINE_RELOC(R_PPC_GOT16_HI,	16)	\
+_ELF_DEFINE_RELOC(R_PPC_GOT16_HA,	17)	\
+_ELF_DEFINE_RELOC(R_PPC_PLTREL24,	18)	\
+_ELF_DEFINE_RELOC(R_PPC_COPY,		19)	\
+_ELF_DEFINE_RELOC(R_PPC_GLOB_DAT,	20)	\
+_ELF_DEFINE_RELOC(R_PPC_JMP_SLOT,	21)	\
+_ELF_DEFINE_RELOC(R_PPC_RELATIVE,	22)	\
+_ELF_DEFINE_RELOC(R_PPC_LOCAL24PC,	23)	\
+_ELF_DEFINE_RELOC(R_PPC_UADDR32,	24)	\
+_ELF_DEFINE_RELOC(R_PPC_UADDR16,	25)	\
+_ELF_DEFINE_RELOC(R_PPC_REL32,		26)	\
+_ELF_DEFINE_RELOC(R_PPC_PLT32,		27)	\
+_ELF_DEFINE_RELOC(R_PPC_PLTREL32,	28)	\
+_ELF_DEFINE_RELOC(R_PPC_PLT16_LO,	29)	\
+_ELF_DEFINE_RELOC(R_PPC_PLT16_HI,	30)	\
+_ELF_DEFINE_RELOC(R_PPC_PLT16_HA,	31)	\
+_ELF_DEFINE_RELOC(R_PPC_SDAREL16,	32)	\
+_ELF_DEFINE_RELOC(R_PPC_SECTOFF,	33)	\
+_ELF_DEFINE_RELOC(R_PPC_SECTOFF_LO,	34)	\
+_ELF_DEFINE_RELOC(R_PPC_SECTOFF_HI,	35)	\
+_ELF_DEFINE_RELOC(R_PPC_SECTOFF_HA,	36)	\
+_ELF_DEFINE_RELOC(R_PPC_ADDR30,		37)	\
+_ELF_DEFINE_RELOC(R_PPC_TLS,		67)	\
+_ELF_DEFINE_RELOC(R_PPC_DTPMOD32,	68)	\
+_ELF_DEFINE_RELOC(R_PPC_TPREL16,	69)	\
+_ELF_DEFINE_RELOC(R_PPC_TPREL16_LO,	70)	\
+_ELF_DEFINE_RELOC(R_PPC_TPREL16_HI,	71)	\
+_ELF_DEFINE_RELOC(R_PPC_TPREL16_HA,	72)	\
+_ELF_DEFINE_RELOC(R_PPC_TPREL32,	73)	\
+_ELF_DEFINE_RELOC(R_PPC_DTPREL16,	74)	\
+_ELF_DEFINE_RELOC(R_PPC_DTPREL16_LO,	75)	\
+_ELF_DEFINE_RELOC(R_PPC_DTPREL16_HI,	76)	\
+_ELF_DEFINE_RELOC(R_PPC_DTPREL16_HA,	77)	\
+_ELF_DEFINE_RELOC(R_PPC_DTPREL32,	78)	\
+_ELF_DEFINE_RELOC(R_PPC_GOT_TLSGD16,	79)	\
+_ELF_DEFINE_RELOC(R_PPC_GOT_TLSGD16_LO,	80)	\
+_ELF_DEFINE_RELOC(R_PPC_GOT_TLSGD16_HI,	81)	\
+_ELF_DEFINE_RELOC(R_PPC_GOT_TLSGD16_HA,	82)	\
+_ELF_DEFINE_RELOC(R_PPC_GOT_TLSLD16,	83)	\
+_ELF_DEFINE_RELOC(R_PPC_GOT_TLSLD16_LO,	84)	\
+_ELF_DEFINE_RELOC(R_PPC_GOT_TLSLD16_HI,	85)	\
+_ELF_DEFINE_RELOC(R_PPC_GOT_TLSLD16_HA,	86)	\
+_ELF_DEFINE_RELOC(R_PPC_GOT_TPREL16,	87)	\
+_ELF_DEFINE_RELOC(R_PPC_GOT_TPREL16_LO,	88)	\
+_ELF_DEFINE_RELOC(R_PPC_GOT_TPREL16_HI,	89)	\
+_ELF_DEFINE_RELOC(R_PPC_GOT_TPREL16_HA,	90)	\
+_ELF_DEFINE_RELOC(R_PPC_GOT_DTPREL16,	91)	\
+_ELF_DEFINE_RELOC(R_PPC_GOT_DTPREL16_LO, 92)	\
+_ELF_DEFINE_RELOC(R_PPC_GOT_DTPREL16_HI, 93)	\
+_ELF_DEFINE_RELOC(R_PPC_GOT_DTPREL16_HA, 94)	\
+_ELF_DEFINE_RELOC(R_PPC_TLSGD,		95)	\
+_ELF_DEFINE_RELOC(R_PPC_TLSLD,		96)	\
+_ELF_DEFINE_RELOC(R_PPC_EMB_NADDR32,	101)	\
+_ELF_DEFINE_RELOC(R_PPC_EMB_NADDR16,	102)	\
+_ELF_DEFINE_RELOC(R_PPC_EMB_NADDR16_LO,	103)	\
+_ELF_DEFINE_RELOC(R_PPC_EMB_NADDR16_HI,	104)	\
+_ELF_DEFINE_RELOC(R_PPC_EMB_NADDR16_HA,	105)	\
+_ELF_DEFINE_RELOC(R_PPC_EMB_SDAI16,	106)	\
+_ELF_DEFINE_RELOC(R_PPC_EMB_SDA2I16,	107)	\
+_ELF_DEFINE_RELOC(R_PPC_EMB_SDA2REL,	108)	\
+_ELF_DEFINE_RELOC(R_PPC_EMB_SDA21,	109)	\
+_ELF_DEFINE_RELOC(R_PPC_EMB_MRKREF,	110)	\
+_ELF_DEFINE_RELOC(R_PPC_EMB_RELSEC16,	111)	\
+_ELF_DEFINE_RELOC(R_PPC_EMB_RELST_LO,	112)	\
+_ELF_DEFINE_RELOC(R_PPC_EMB_RELST_HI,	113)	\
+_ELF_DEFINE_RELOC(R_PPC_EMB_RELST_HA,	114)	\
+_ELF_DEFINE_RELOC(R_PPC_EMB_BIT_FLD,	115)	\
+_ELF_DEFINE_RELOC(R_PPC_EMB_RELSDA,	116)	\
+
+#define	_ELF_DEFINE_PPC64_RELOCATIONS()			\
+_ELF_DEFINE_RELOC(R_PPC64_NONE,			0)	\
+_ELF_DEFINE_RELOC(R_PPC64_ADDR32,		1)	\
+_ELF_DEFINE_RELOC(R_PPC64_ADDR24,		2)	\
+_ELF_DEFINE_RELOC(R_PPC64_ADDR16,		3)	\
+_ELF_DEFINE_RELOC(R_PPC64_ADDR16_LO,		4)	\
+_ELF_DEFINE_RELOC(R_PPC64_ADDR16_HI,		5)	\
+_ELF_DEFINE_RELOC(R_PPC64_ADDR16_HA,		6)	\
+_ELF_DEFINE_RELOC(R_PPC64_ADDR14,		7)	\
+_ELF_DEFINE_RELOC(R_PPC64_ADDR14_BRTAKEN,	8)	\
+_ELF_DEFINE_RELOC(R_PPC64_ADDR14_BRNTAKEN,	9)	\
+_ELF_DEFINE_RELOC(R_PPC64_REL24,		10)	\
+_ELF_DEFINE_RELOC(R_PPC64_REL14,		11)	\
+_ELF_DEFINE_RELOC(R_PPC64_REL14_BRTAKEN,	12)	\
+_ELF_DEFINE_RELOC(R_PPC64_REL14_BRNTAKEN,	13)	\
+_ELF_DEFINE_RELOC(R_PPC64_GOT16,		14)	\
+_ELF_DEFINE_RELOC(R_PPC64_GOT16_LO,		15)	\
+_ELF_DEFINE_RELOC(R_PPC64_GOT16_HI,		16)	\
+_ELF_DEFINE_RELOC(R_PPC64_GOT16_HA,		17)	\
+_ELF_DEFINE_RELOC(R_PPC64_COPY,			19)	\
+_ELF_DEFINE_RELOC(R_PPC64_GLOB_DAT,		20)	\
+_ELF_DEFINE_RELOC(R_PPC64_JMP_SLOT,		21)	\
+_ELF_DEFINE_RELOC(R_PPC64_RELATIVE,		22)	\
+_ELF_DEFINE_RELOC(R_PPC64_UADDR32,		24)	\
+_ELF_DEFINE_RELOC(R_PPC64_UADDR16,		25)	\
+_ELF_DEFINE_RELOC(R_PPC64_REL32,		26)	\
+_ELF_DEFINE_RELOC(R_PPC64_PLT32,		27)	\
+_ELF_DEFINE_RELOC(R_PPC64_PLTREL32,		28)	\
+_ELF_DEFINE_RELOC(R_PPC64_PLT16_LO,		29)	\
+_ELF_DEFINE_RELOC(R_PPC64_PLT16_HI,		30)	\
+_ELF_DEFINE_RELOC(R_PPC64_PLT16_HA,		31)	\
+_ELF_DEFINE_RELOC(R_PPC64_SECTOFF,		33)	\
+_ELF_DEFINE_RELOC(R_PPC64_SECTOFF_LO,		34)	\
+_ELF_DEFINE_RELOC(R_PPC64_SECTOFF_HI,		35)	\
+_ELF_DEFINE_RELOC(R_PPC64_SECTOFF_HA,		36)	\
+_ELF_DEFINE_RELOC(R_PPC64_ADDR30,		37)	\
+_ELF_DEFINE_RELOC(R_PPC64_ADDR64,		38)	\
+_ELF_DEFINE_RELOC(R_PPC64_ADDR16_HIGHER,	39)	\
+_ELF_DEFINE_RELOC(R_PPC64_ADDR16_HIGHERA,	40)	\
+_ELF_DEFINE_RELOC(R_PPC64_ADDR16_HIGHEST,	41)	\
+_ELF_DEFINE_RELOC(R_PPC64_ADDR16_HIGHESTA,	42)	\
+_ELF_DEFINE_RELOC(R_PPC64_UADDR64,		43)	\
+_ELF_DEFINE_RELOC(R_PPC64_REL64,		44)	\
+_ELF_DEFINE_RELOC(R_PPC64_PLT64,		45)	\
+_ELF_DEFINE_RELOC(R_PPC64_PLTREL64,		46)	\
+_ELF_DEFINE_RELOC(R_PPC64_TOC16,		47)	\
+_ELF_DEFINE_RELOC(R_PPC64_TOC16_LO,		48)	\
+_ELF_DEFINE_RELOC(R_PPC64_TOC16_HI,		49)	\
+_ELF_DEFINE_RELOC(R_PPC64_TOC16_HA,		50)	\
+_ELF_DEFINE_RELOC(R_PPC64_TOC,			51)	\
+_ELF_DEFINE_RELOC(R_PPC64_PLTGOT16,		52)	\
+_ELF_DEFINE_RELOC(R_PPC64_PLTGOT16_LO,		53)	\
+_ELF_DEFINE_RELOC(R_PPC64_PLTGOT16_HI,		54)	\
+_ELF_DEFINE_RELOC(R_PPC64_PLTGOT16_HA,		55)	\
+_ELF_DEFINE_RELOC(R_PPC64_ADDR16_DS,		56)	\
+_ELF_DEFINE_RELOC(R_PPC64_ADDR16_LO_DS,		57)	\
+_ELF_DEFINE_RELOC(R_PPC64_GOT16_DS,		58)	\
+_ELF_DEFINE_RELOC(R_PPC64_GOT16_LO_DS,		59)	\
+_ELF_DEFINE_RELOC(R_PPC64_PLT16_LO_DS,		60)	\
+_ELF_DEFINE_RELOC(R_PPC64_SECTOFF_DS,		61)	\
+_ELF_DEFINE_RELOC(R_PPC64_SECTOFF_LO_DS,	62)	\
+_ELF_DEFINE_RELOC(R_PPC64_TOC16_DS,		63)	\
+_ELF_DEFINE_RELOC(R_PPC64_TOC16_LO_DS,		64)	\
+_ELF_DEFINE_RELOC(R_PPC64_PLTGOT16_DS,		65)	\
+_ELF_DEFINE_RELOC(R_PPC64_PLTGOT16_LO_DS,	66)	\
+_ELF_DEFINE_RELOC(R_PPC64_TLS,			67)	\
+_ELF_DEFINE_RELOC(R_PPC64_DTPMOD64,		68)	\
+_ELF_DEFINE_RELOC(R_PPC64_TPREL16,		69)	\
+_ELF_DEFINE_RELOC(R_PPC64_TPREL16_LO,		60)	\
+_ELF_DEFINE_RELOC(R_PPC64_TPREL16_HI,		71)	\
+_ELF_DEFINE_RELOC(R_PPC64_TPREL16_HA,		72)	\
+_ELF_DEFINE_RELOC(R_PPC64_TPREL64,		73)	\
+_ELF_DEFINE_RELOC(R_PPC64_DTPREL16,		74)	\
+_ELF_DEFINE_RELOC(R_PPC64_DTPREL16_LO,		75)	\
+_ELF_DEFINE_RELOC(R_PPC64_DTPREL16_HI,		76)	\
+_ELF_DEFINE_RELOC(R_PPC64_DTPREL16_HA,		77)	\
+_ELF_DEFINE_RELOC(R_PPC64_DTPREL64,		78)	\
+_ELF_DEFINE_RELOC(R_PPC64_GOT_TLSGD16,		79)	\
+_ELF_DEFINE_RELOC(R_PPC64_GOT_TLSGD16_LO,	80)	\
+_ELF_DEFINE_RELOC(R_PPC64_GOT_TLSGD16_HI,	81)	\
+_ELF_DEFINE_RELOC(R_PPC64_GOT_TLSGD16_HA,	82)	\
+_ELF_DEFINE_RELOC(R_PPC64_GOT_TLSLD16,		83)	\
+_ELF_DEFINE_RELOC(R_PPC64_GOT_TLSLD16_LO,	84)	\
+_ELF_DEFINE_RELOC(R_PPC64_GOT_TLSLD16_HI,	85)	\
+_ELF_DEFINE_RELOC(R_PPC64_GOT_TLSLD16_HA,	86)	\
+_ELF_DEFINE_RELOC(R_PPC64_GOT_TPREL16_DS,	87)	\
+_ELF_DEFINE_RELOC(R_PPC64_GOT_TPREL16_LO_DS,	88)	\
+_ELF_DEFINE_RELOC(R_PPC64_GOT_TPREL16_HI,	89)	\
+_ELF_DEFINE_RELOC(R_PPC64_GOT_TPREL16_HA,	90)	\
+_ELF_DEFINE_RELOC(R_PPC64_GOT_DTPREL16_DS,	91)	\
+_ELF_DEFINE_RELOC(R_PPC64_GOT_DTPREL16_LO_DS,	92)	\
+_ELF_DEFINE_RELOC(R_PPC64_GOT_DTPREL16_HI,	93)	\
+_ELF_DEFINE_RELOC(R_PPC64_GOT_DTPREL16_HA,	94)	\
+_ELF_DEFINE_RELOC(R_PPC64_TPREL16_DS,		95)	\
+_ELF_DEFINE_RELOC(R_PPC64_TPREL16_LO_DS,	96)	\
+_ELF_DEFINE_RELOC(R_PPC64_TPREL16_HIGHER,	97)	\
+_ELF_DEFINE_RELOC(R_PPC64_TPREL16_HIGHERA,	98)	\
+_ELF_DEFINE_RELOC(R_PPC64_TPREL16_HIGHEST,	99)	\
+_ELF_DEFINE_RELOC(R_PPC64_TPREL16_HIGHESTA,	100)	\
+_ELF_DEFINE_RELOC(R_PPC64_DTPREL16_DS,		101)	\
+_ELF_DEFINE_RELOC(R_PPC64_DTPREL16_LO_DS,	102)	\
+_ELF_DEFINE_RELOC(R_PPC64_DTPREL16_HIGHER,	103)	\
+_ELF_DEFINE_RELOC(R_PPC64_DTPREL16_HIGHERA,	104)	\
+_ELF_DEFINE_RELOC(R_PPC64_DTPREL16_HIGHEST,	105)	\
+_ELF_DEFINE_RELOC(R_PPC64_DTPREL16_HIGHESTA,	106)	\
+_ELF_DEFINE_RELOC(R_PPC64_TLSGD,		107)	\
+_ELF_DEFINE_RELOC(R_PPC64_TLSLD,		108)
+
+#define	_ELF_DEFINE_RISCV_RELOCATIONS()			\
+_ELF_DEFINE_RELOC(R_RISCV_NONE,			0)	\
+_ELF_DEFINE_RELOC(R_RISCV_32,			1)	\
+_ELF_DEFINE_RELOC(R_RISCV_64,			2)	\
+_ELF_DEFINE_RELOC(R_RISCV_RELATIVE,		3)	\
+_ELF_DEFINE_RELOC(R_RISCV_COPY,			4)	\
+_ELF_DEFINE_RELOC(R_RISCV_JUMP_SLOT,		5)	\
+_ELF_DEFINE_RELOC(R_RISCV_TLS_DTPMOD32,		6)	\
+_ELF_DEFINE_RELOC(R_RISCV_TLS_DTPMOD64,		7)	\
+_ELF_DEFINE_RELOC(R_RISCV_TLS_DTPREL32,		8)	\
+_ELF_DEFINE_RELOC(R_RISCV_TLS_DTPREL64,		9)	\
+_ELF_DEFINE_RELOC(R_RISCV_TLS_TPREL32,		10)	\
+_ELF_DEFINE_RELOC(R_RISCV_TLS_TPREL64,		11)	\
+_ELF_DEFINE_RELOC(R_RISCV_BRANCH,		16)	\
+_ELF_DEFINE_RELOC(R_RISCV_JAL,			17)	\
+_ELF_DEFINE_RELOC(R_RISCV_CALL,			18)	\
+_ELF_DEFINE_RELOC(R_RISCV_CALL_PLT,		19)	\
+_ELF_DEFINE_RELOC(R_RISCV_GOT_HI20,		20)	\
+_ELF_DEFINE_RELOC(R_RISCV_TLS_GOT_HI20,		21)	\
+_ELF_DEFINE_RELOC(R_RISCV_TLS_GD_HI20,		22)	\
+_ELF_DEFINE_RELOC(R_RISCV_PCREL_HI20,		23)	\
+_ELF_DEFINE_RELOC(R_RISCV_PCREL_LO12_I,		24)	\
+_ELF_DEFINE_RELOC(R_RISCV_PCREL_LO12_S,		25)	\
+_ELF_DEFINE_RELOC(R_RISCV_HI20,			26)	\
+_ELF_DEFINE_RELOC(R_RISCV_LO12_I,		27)	\
+_ELF_DEFINE_RELOC(R_RISCV_LO12_S,		28)	\
+_ELF_DEFINE_RELOC(R_RISCV_TPREL_HI20,		29)	\
+_ELF_DEFINE_RELOC(R_RISCV_TPREL_LO12_I,		30)	\
+_ELF_DEFINE_RELOC(R_RISCV_TPREL_LO12_S,		31)	\
+_ELF_DEFINE_RELOC(R_RISCV_TPREL_ADD,		32)	\
+_ELF_DEFINE_RELOC(R_RISCV_ADD8,			33)	\
+_ELF_DEFINE_RELOC(R_RISCV_ADD16,		34)	\
+_ELF_DEFINE_RELOC(R_RISCV_ADD32,		35)	\
+_ELF_DEFINE_RELOC(R_RISCV_ADD64,		36)	\
+_ELF_DEFINE_RELOC(R_RISCV_SUB8,			37)	\
+_ELF_DEFINE_RELOC(R_RISCV_SUB16,		38)	\
+_ELF_DEFINE_RELOC(R_RISCV_SUB32,		39)	\
+_ELF_DEFINE_RELOC(R_RISCV_SUB64,		40)	\
+_ELF_DEFINE_RELOC(R_RISCV_GNU_VTINHERIT,	41)	\
+_ELF_DEFINE_RELOC(R_RISCV_GNU_VTENTRY,		42)	\
+_ELF_DEFINE_RELOC(R_RISCV_ALIGN,		43)	\
+_ELF_DEFINE_RELOC(R_RISCV_RVC_BRANCH,		44)	\
+_ELF_DEFINE_RELOC(R_RISCV_RVC_JUMP,		45)	\
+_ELF_DEFINE_RELOC(R_RISCV_RVC_LUI,		46)	\
+_ELF_DEFINE_RELOC(R_RISCV_GPREL_I,		47)	\
+_ELF_DEFINE_RELOC(R_RISCV_GPREL_S,		48)
+
+#define	_ELF_DEFINE_SPARC_RELOCATIONS()		\
+_ELF_DEFINE_RELOC(R_SPARC_NONE,		0)	\
+_ELF_DEFINE_RELOC(R_SPARC_8,		1)	\
+_ELF_DEFINE_RELOC(R_SPARC_16,		2)	\
+_ELF_DEFINE_RELOC(R_SPARC_32, 		3)	\
+_ELF_DEFINE_RELOC(R_SPARC_DISP8,	4)	\
+_ELF_DEFINE_RELOC(R_SPARC_DISP16,	5)	\
+_ELF_DEFINE_RELOC(R_SPARC_DISP32,	6)	\
+_ELF_DEFINE_RELOC(R_SPARC_WDISP30,	7)	\
+_ELF_DEFINE_RELOC(R_SPARC_WDISP22,	8)	\
+_ELF_DEFINE_RELOC(R_SPARC_HI22,		9)	\
+_ELF_DEFINE_RELOC(R_SPARC_22,		10)	\
+_ELF_DEFINE_RELOC(R_SPARC_13,		11)	\
+_ELF_DEFINE_RELOC(R_SPARC_LO10,		12)	\
+_ELF_DEFINE_RELOC(R_SPARC_GOT10,	13)	\
+_ELF_DEFINE_RELOC(R_SPARC_GOT13,	14)	\
+_ELF_DEFINE_RELOC(R_SPARC_GOT22,	15)	\
+_ELF_DEFINE_RELOC(R_SPARC_PC10,		16)	\
+_ELF_DEFINE_RELOC(R_SPARC_PC22,		17)	\
+_ELF_DEFINE_RELOC(R_SPARC_WPLT30,	18)	\
+_ELF_DEFINE_RELOC(R_SPARC_COPY,		19)	\
+_ELF_DEFINE_RELOC(R_SPARC_GLOB_DAT,	20)	\
+_ELF_DEFINE_RELOC(R_SPARC_JMP_SLOT,	21)	\
+_ELF_DEFINE_RELOC(R_SPARC_RELATIVE,	22)	\
+_ELF_DEFINE_RELOC(R_SPARC_UA32,		23)	\
+_ELF_DEFINE_RELOC(R_SPARC_PLT32,	24)	\
+_ELF_DEFINE_RELOC(R_SPARC_HIPLT22,	25)	\
+_ELF_DEFINE_RELOC(R_SPARC_LOPLT10,	26)	\
+_ELF_DEFINE_RELOC(R_SPARC_PCPLT32,	27)	\
+_ELF_DEFINE_RELOC(R_SPARC_PCPLT22,	28)	\
+_ELF_DEFINE_RELOC(R_SPARC_PCPLT10,	29)	\
+_ELF_DEFINE_RELOC(R_SPARC_10,		30)	\
+_ELF_DEFINE_RELOC(R_SPARC_11,		31)	\
+_ELF_DEFINE_RELOC(R_SPARC_64,		32)	\
+_ELF_DEFINE_RELOC(R_SPARC_OLO10,	33)	\
+_ELF_DEFINE_RELOC(R_SPARC_HH22,		34)	\
+_ELF_DEFINE_RELOC(R_SPARC_HM10,		35)	\
+_ELF_DEFINE_RELOC(R_SPARC_LM22,		36)	\
+_ELF_DEFINE_RELOC(R_SPARC_PC_HH22,	37)	\
+_ELF_DEFINE_RELOC(R_SPARC_PC_HM10,	38)	\
+_ELF_DEFINE_RELOC(R_SPARC_PC_LM22,	39)	\
+_ELF_DEFINE_RELOC(R_SPARC_WDISP16,	40)	\
+_ELF_DEFINE_RELOC(R_SPARC_WDISP19,	41)	\
+_ELF_DEFINE_RELOC(R_SPARC_GLOB_JMP,	42)	\
+_ELF_DEFINE_RELOC(R_SPARC_7,		43)	\
+_ELF_DEFINE_RELOC(R_SPARC_5,		44)	\
+_ELF_DEFINE_RELOC(R_SPARC_6,		45)	\
+_ELF_DEFINE_RELOC(R_SPARC_DISP64,	46)	\
+_ELF_DEFINE_RELOC(R_SPARC_PLT64,	47)	\
+_ELF_DEFINE_RELOC(R_SPARC_HIX22,	48)	\
+_ELF_DEFINE_RELOC(R_SPARC_LOX10,	49)	\
+_ELF_DEFINE_RELOC(R_SPARC_H44,		50)	\
+_ELF_DEFINE_RELOC(R_SPARC_M44,		51)	\
+_ELF_DEFINE_RELOC(R_SPARC_L44,		52)	\
+_ELF_DEFINE_RELOC(R_SPARC_REGISTER,	53)	\
+_ELF_DEFINE_RELOC(R_SPARC_UA64,		54)	\
+_ELF_DEFINE_RELOC(R_SPARC_UA16,		55)	\
+_ELF_DEFINE_RELOC(R_SPARC_TLS_GD_HI22,	56)	\
+_ELF_DEFINE_RELOC(R_SPARC_TLS_GD_LO10,	57)	\
+_ELF_DEFINE_RELOC(R_SPARC_TLS_GD_ADD,	58)	\
+_ELF_DEFINE_RELOC(R_SPARC_TLS_GD_CALL,	59)	\
+_ELF_DEFINE_RELOC(R_SPARC_TLS_LDM_HI22,	60)	\
+_ELF_DEFINE_RELOC(R_SPARC_TLS_LDM_LO10,	61)	\
+_ELF_DEFINE_RELOC(R_SPARC_TLS_LDM_ADD,	62)	\
+_ELF_DEFINE_RELOC(R_SPARC_TLS_LDM_CALL,	63)	\
+_ELF_DEFINE_RELOC(R_SPARC_TLS_LDO_HIX22, 64)	\
+_ELF_DEFINE_RELOC(R_SPARC_TLS_LDO_LOX10, 65)	\
+_ELF_DEFINE_RELOC(R_SPARC_TLS_LDO_ADD,	66)	\
+_ELF_DEFINE_RELOC(R_SPARC_TLS_IE_HI22,	67)	\
+_ELF_DEFINE_RELOC(R_SPARC_TLS_IE_LO10,	68)	\
+_ELF_DEFINE_RELOC(R_SPARC_TLS_IE_LD,	69)	\
+_ELF_DEFINE_RELOC(R_SPARC_TLS_IE_LDX,	70)	\
+_ELF_DEFINE_RELOC(R_SPARC_TLS_IE_ADD,	71)	\
+_ELF_DEFINE_RELOC(R_SPARC_TLS_LE_HIX22,	72)	\
+_ELF_DEFINE_RELOC(R_SPARC_TLS_LE_LOX10,	73)	\
+_ELF_DEFINE_RELOC(R_SPARC_TLS_DTPMOD32,	74)	\
+_ELF_DEFINE_RELOC(R_SPARC_TLS_DTPMOD64,	75)	\
+_ELF_DEFINE_RELOC(R_SPARC_TLS_DTPOFF32,	76)	\
+_ELF_DEFINE_RELOC(R_SPARC_TLS_DTPOFF64,	77)	\
+_ELF_DEFINE_RELOC(R_SPARC_TLS_TPOFF32,	78)	\
+_ELF_DEFINE_RELOC(R_SPARC_TLS_TPOFF64,	79)	\
+_ELF_DEFINE_RELOC(R_SPARC_GOTDATA_HIX22, 80)	\
+_ELF_DEFINE_RELOC(R_SPARC_GOTDATA_LOX10, 81)	\
+_ELF_DEFINE_RELOC(R_SPARC_GOTDATA_OP_HIX22, 82)	\
+_ELF_DEFINE_RELOC(R_SPARC_GOTDATA_OP_LOX10, 83)	\
+_ELF_DEFINE_RELOC(R_SPARC_GOTDATA_OP,	84)	\
+_ELF_DEFINE_RELOC(R_SPARC_H34,		85)
+
+#define	_ELF_DEFINE_X86_64_RELOCATIONS()	\
+_ELF_DEFINE_RELOC(R_X86_64_NONE,	0)	\
+_ELF_DEFINE_RELOC(R_X86_64_64,		1)	\
+_ELF_DEFINE_RELOC(R_X86_64_PC32,	2)	\
+_ELF_DEFINE_RELOC(R_X86_64_GOT32,	3)	\
+_ELF_DEFINE_RELOC(R_X86_64_PLT32,	4)	\
+_ELF_DEFINE_RELOC(R_X86_64_COPY,	5)	\
+_ELF_DEFINE_RELOC(R_X86_64_GLOB_DAT,	6)	\
+_ELF_DEFINE_RELOC(R_X86_64_JUMP_SLOT,	7)	\
+_ELF_DEFINE_RELOC(R_X86_64_RELATIVE,	8)	\
+_ELF_DEFINE_RELOC(R_X86_64_GOTPCREL,	9)	\
+_ELF_DEFINE_RELOC(R_X86_64_32,		10)	\
+_ELF_DEFINE_RELOC(R_X86_64_32S,		11)	\
+_ELF_DEFINE_RELOC(R_X86_64_16,		12)	\
+_ELF_DEFINE_RELOC(R_X86_64_PC16,	13)	\
+_ELF_DEFINE_RELOC(R_X86_64_8,		14)	\
+_ELF_DEFINE_RELOC(R_X86_64_PC8,		15)	\
+_ELF_DEFINE_RELOC(R_X86_64_DTPMOD64,	16)	\
+_ELF_DEFINE_RELOC(R_X86_64_DTPOFF64,	17)	\
+_ELF_DEFINE_RELOC(R_X86_64_TPOFF64,	18)	\
+_ELF_DEFINE_RELOC(R_X86_64_TLSGD,	19)	\
+_ELF_DEFINE_RELOC(R_X86_64_TLSLD,	20)	\
+_ELF_DEFINE_RELOC(R_X86_64_DTPOFF32,	21)	\
+_ELF_DEFINE_RELOC(R_X86_64_GOTTPOFF,	22)	\
+_ELF_DEFINE_RELOC(R_X86_64_TPOFF32,	23)	\
+_ELF_DEFINE_RELOC(R_X86_64_PC64,	24)	\
+_ELF_DEFINE_RELOC(R_X86_64_GOTOFF64,	25)	\
+_ELF_DEFINE_RELOC(R_X86_64_GOTPC32,	26)	\
+_ELF_DEFINE_RELOC(R_X86_64_GOT64,	27)	\
+_ELF_DEFINE_RELOC(R_X86_64_GOTPCREL64,	28)	\
+_ELF_DEFINE_RELOC(R_X86_64_GOTPC64,	29)	\
+_ELF_DEFINE_RELOC(R_X86_64_GOTPLT64,	30)	\
+_ELF_DEFINE_RELOC(R_X86_64_PLTOFF64,	31)	\
+_ELF_DEFINE_RELOC(R_X86_64_SIZE32,	32)	\
+_ELF_DEFINE_RELOC(R_X86_64_SIZE64,	33)	\
+_ELF_DEFINE_RELOC(R_X86_64_GOTPC32_TLSDESC, 34)	\
+_ELF_DEFINE_RELOC(R_X86_64_TLSDESC_CALL, 35)	\
+_ELF_DEFINE_RELOC(R_X86_64_TLSDESC,	36)	\
+_ELF_DEFINE_RELOC(R_X86_64_IRELATIVE,	37)	\
+_ELF_DEFINE_RELOC(R_X86_64_RELATIVE64,	38)	\
+_ELF_DEFINE_RELOC(R_X86_64_GOTPCRELX,	41)	\
+_ELF_DEFINE_RELOC(R_X86_64_REX_GOTPCRELX, 42)
+
+#define	_ELF_DEFINE_RELOCATIONS()		\
+_ELF_DEFINE_386_RELOCATIONS()			\
+_ELF_DEFINE_AARCH64_RELOCATIONS()		\
+_ELF_DEFINE_AMD64_RELOCATIONS()			\
+_ELF_DEFINE_ARM_RELOCATIONS()			\
+_ELF_DEFINE_IA64_RELOCATIONS()			\
+_ELF_DEFINE_MIPS_RELOCATIONS()			\
+_ELF_DEFINE_PPC32_RELOCATIONS()			\
+_ELF_DEFINE_PPC64_RELOCATIONS()			\
+_ELF_DEFINE_RISCV_RELOCATIONS()			\
+_ELF_DEFINE_SPARC_RELOCATIONS()			\
+_ELF_DEFINE_X86_64_RELOCATIONS()
+
+#undef	_ELF_DEFINE_RELOC
+#define	_ELF_DEFINE_RELOC(N, V)		N = V ,
+enum {
+	_ELF_DEFINE_RELOCATIONS()
+	R__LAST__
+};
+
+#define	PN_XNUM			0xFFFFU /* Use extended section numbering. */
+
+/**
+ ** ELF Types.
+ **/
+
+typedef uint32_t	Elf32_Addr;	/* Program address. */
+typedef uint8_t		Elf32_Byte;	/* Unsigned tiny integer. */
+typedef uint16_t	Elf32_Half;	/* Unsigned medium integer. */
+typedef uint32_t	Elf32_Off;	/* File offset. */
+typedef uint16_t	Elf32_Section;	/* Section index. */
+typedef int32_t		Elf32_Sword;	/* Signed integer. */
+typedef uint32_t	Elf32_Word;	/* Unsigned integer. */
+typedef uint64_t	Elf32_Lword;	/* Unsigned long integer. */
+
+typedef uint64_t	Elf64_Addr;	/* Program address. */
+typedef uint8_t		Elf64_Byte;	/* Unsigned tiny integer. */
+typedef uint16_t	Elf64_Half;	/* Unsigned medium integer. */
+typedef uint64_t	Elf64_Off;	/* File offset. */
+typedef uint16_t	Elf64_Section;	/* Section index. */
+typedef int32_t		Elf64_Sword;	/* Signed integer. */
+typedef uint32_t	Elf64_Word;	/* Unsigned integer. */
+typedef uint64_t	Elf64_Lword;	/* Unsigned long integer. */
+typedef uint64_t	Elf64_Xword;	/* Unsigned long integer. */
+typedef int64_t		Elf64_Sxword;	/* Signed long integer. */
+
+
+/*
+ * Capability descriptors.
+ */
+
+/* 32-bit capability descriptor. */
+typedef struct {
+	Elf32_Word	c_tag;	     /* Type of entry. */
+	union {
+		Elf32_Word	c_val; /* Integer value. */
+		Elf32_Addr	c_ptr; /* Pointer value. */
+	} c_un;
+} Elf32_Cap;
+
+/* 64-bit capability descriptor. */
+typedef struct {
+	Elf64_Xword	c_tag;	     /* Type of entry. */
+	union {
+		Elf64_Xword	c_val; /* Integer value. */
+		Elf64_Addr	c_ptr; /* Pointer value. */
+	} c_un;
+} Elf64_Cap;
+
+/*
+ * MIPS .conflict section entries.
+ */
+
+/* 32-bit entry. */
+typedef struct {
+	Elf32_Addr	c_index;
+} Elf32_Conflict;
+
+/* 64-bit entry. */
+typedef struct {
+	Elf64_Addr	c_index;
+} Elf64_Conflict;
+
+/*
+ * Dynamic section entries.
+ */
+
+/* 32-bit entry. */
+typedef struct {
+	Elf32_Sword	d_tag;	     /* Type of entry. */
+	union {
+		Elf32_Word	d_val; /* Integer value. */
+		Elf32_Addr	d_ptr; /* Pointer value. */
+	} d_un;
+} Elf32_Dyn;
+
+/* 64-bit entry. */
+typedef struct {
+	Elf64_Sxword	d_tag;	     /* Type of entry. */
+	union {
+		Elf64_Xword	d_val; /* Integer value. */
+		Elf64_Addr	d_ptr; /* Pointer value; */
+	} d_un;
+} Elf64_Dyn;
+
+
+/*
+ * The executable header (EHDR).
+ */
+
+/* 32 bit EHDR. */
+typedef struct {
+	unsigned char   e_ident[EI_NIDENT]; /* ELF identification. */
+	Elf32_Half      e_type;	     /* Object file type (ET_*). */
+	Elf32_Half      e_machine;   /* Machine type (EM_*). */
+	Elf32_Word      e_version;   /* File format version (EV_*). */
+	Elf32_Addr      e_entry;     /* Start address. */
+	Elf32_Off       e_phoff;     /* File offset to the PHDR table. */
+	Elf32_Off       e_shoff;     /* File offset to the SHDRheader. */
+	Elf32_Word      e_flags;     /* Flags (EF_*). */
+	Elf32_Half      e_ehsize;    /* Elf header size in bytes. */
+	Elf32_Half      e_phentsize; /* PHDR table entry size in bytes. */
+	Elf32_Half      e_phnum;     /* Number of PHDR entries. */
+	Elf32_Half      e_shentsize; /* SHDR table entry size in bytes. */
+	Elf32_Half      e_shnum;     /* Number of SHDR entries. */
+	Elf32_Half      e_shstrndx;  /* Index of section name string table. */
+} Elf32_Ehdr;
+
+
+/* 64 bit EHDR. */
+typedef struct {
+	unsigned char   e_ident[EI_NIDENT]; /* ELF identification. */
+	Elf64_Half      e_type;	     /* Object file type (ET_*). */
+	Elf64_Half      e_machine;   /* Machine type (EM_*). */
+	Elf64_Word      e_version;   /* File format version (EV_*). */
+	Elf64_Addr      e_entry;     /* Start address. */
+	Elf64_Off       e_phoff;     /* File offset to the PHDR table. */
+	Elf64_Off       e_shoff;     /* File offset to the SHDRheader. */
+	Elf64_Word      e_flags;     /* Flags (EF_*). */
+	Elf64_Half      e_ehsize;    /* Elf header size in bytes. */
+	Elf64_Half      e_phentsize; /* PHDR table entry size in bytes. */
+	Elf64_Half      e_phnum;     /* Number of PHDR entries. */
+	Elf64_Half      e_shentsize; /* SHDR table entry size in bytes. */
+	Elf64_Half      e_shnum;     /* Number of SHDR entries. */
+	Elf64_Half      e_shstrndx;  /* Index of section name string table. */
+} Elf64_Ehdr;
+
+
+/*
+ * Shared object information.
+ */
+
+/* 32-bit entry. */
+typedef struct {
+	Elf32_Word l_name;	     /* The name of a shared object. */
+	Elf32_Word l_time_stamp;     /* 32-bit timestamp. */
+	Elf32_Word l_checksum;	     /* Checksum of visible symbols, sizes. */
+	Elf32_Word l_version;	     /* Interface version string index. */
+	Elf32_Word l_flags;	     /* Flags (LL_*). */
+} Elf32_Lib;
+
+/* 64-bit entry. */
+typedef struct {
+	Elf64_Word l_name;	     /* The name of a shared object. */
+	Elf64_Word l_time_stamp;     /* 32-bit timestamp. */
+	Elf64_Word l_checksum;	     /* Checksum of visible symbols, sizes. */
+	Elf64_Word l_version;	     /* Interface version string index. */
+	Elf64_Word l_flags;	     /* Flags (LL_*). */
+} Elf64_Lib;
+
+#define	_ELF_DEFINE_LL_FLAGS()			\
+_ELF_DEFINE_LL(LL_NONE,			0,	\
+	"no flags")				\
+_ELF_DEFINE_LL(LL_EXACT_MATCH,		0x1,	\
+	"require an exact match")		\
+_ELF_DEFINE_LL(LL_IGNORE_INT_VER,	0x2,	\
+	"ignore version incompatibilities")	\
+_ELF_DEFINE_LL(LL_REQUIRE_MINOR,	0x4,	\
+	"")					\
+_ELF_DEFINE_LL(LL_EXPORTS,		0x8,	\
+	"")					\
+_ELF_DEFINE_LL(LL_DELAY_LOAD,		0x10,	\
+	"")					\
+_ELF_DEFINE_LL(LL_DELTA,		0x20,	\
+	"")
+
+#undef	_ELF_DEFINE_LL
+#define	_ELF_DEFINE_LL(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_LL_FLAGS()
+	LL__LAST__
+};
+
+/*
+ * Note tags
+ */
+
+#define	_ELF_DEFINE_NOTE_ENTRY_TYPES()					\
+_ELF_DEFINE_NT(NT_ABI_TAG,	1,	"Tag indicating the ABI")	\
+_ELF_DEFINE_NT(NT_GNU_HWCAP,	2,	"Hardware capabilities")	\
+_ELF_DEFINE_NT(NT_GNU_BUILD_ID,	3,	"Build id, set by ld(1)")	\
+_ELF_DEFINE_NT(NT_GNU_GOLD_VERSION, 4,					\
+	"Version number of the GNU gold linker")			\
+_ELF_DEFINE_NT(NT_PRSTATUS,	1,	"Process status")		\
+_ELF_DEFINE_NT(NT_FPREGSET,	2,	"Floating point information")	\
+_ELF_DEFINE_NT(NT_PRPSINFO,	3,	"Process information")		\
+_ELF_DEFINE_NT(NT_AUXV,		6,	"Auxiliary vector")		\
+_ELF_DEFINE_NT(NT_PRXFPREG,	0x46E62B7FUL,				\
+	"Linux user_xfpregs structure")					\
+_ELF_DEFINE_NT(NT_PSTATUS,	10,	"Linux process status")		\
+_ELF_DEFINE_NT(NT_FPREGS,	12,	"Linux floating point regset")	\
+_ELF_DEFINE_NT(NT_PSINFO,	13,	"Linux process information")	\
+_ELF_DEFINE_NT(NT_LWPSTATUS,	16,	"Linux lwpstatus_t type")	\
+_ELF_DEFINE_NT(NT_LWPSINFO,	17,	"Linux lwpinfo_t type")
+
+#undef	_ELF_DEFINE_NT
+#define	_ELF_DEFINE_NT(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_NOTE_ENTRY_TYPES()
+	NT__LAST__
+};
+
+/* Aliases for the ABI tag. */
+#define	NT_FREEBSD_ABI_TAG	NT_ABI_TAG
+#define	NT_GNU_ABI_TAG		NT_ABI_TAG
+#define	NT_NETBSD_IDENT		NT_ABI_TAG
+#define	NT_OPENBSD_IDENT	NT_ABI_TAG
+
+/*
+ * Note descriptors.
+ */
+
+typedef	struct {
+	uint32_t	n_namesz;    /* Length of note's name. */
+	uint32_t	n_descsz;    /* Length of note's value. */
+	uint32_t	n_type;	     /* Type of note. */
+} Elf_Note;
+
+typedef Elf_Note Elf32_Nhdr;	     /* 32-bit note header. */
+typedef Elf_Note Elf64_Nhdr;	     /* 64-bit note header. */
+
+/*
+ * MIPS ELF options descriptor header.
+ */
+
+typedef struct {
+	Elf64_Byte	kind;        /* Type of options. */
+	Elf64_Byte     	size;	     /* Size of option descriptor. */
+	Elf64_Half	section;     /* Index of section affected. */
+	Elf64_Word	info;        /* Kind-specific information. */
+} Elf_Options;
+
+/*
+ * Option kinds.
+ */
+
+#define	_ELF_DEFINE_OPTION_KINDS()					\
+_ELF_DEFINE_ODK(ODK_NULL,       0,      "undefined")			\
+_ELF_DEFINE_ODK(ODK_REGINFO,    1,      "register usage info")		\
+_ELF_DEFINE_ODK(ODK_EXCEPTIONS, 2,      "exception processing info")	\
+_ELF_DEFINE_ODK(ODK_PAD,        3,      "section padding")		\
+_ELF_DEFINE_ODK(ODK_HWPATCH,    4,      "hardware patch applied")	\
+_ELF_DEFINE_ODK(ODK_FILL,       5,      "fill value used by linker")	\
+_ELF_DEFINE_ODK(ODK_TAGS,       6,      "reserved space for tools")	\
+_ELF_DEFINE_ODK(ODK_HWAND,      7,      "hardware AND patch applied")	\
+_ELF_DEFINE_ODK(ODK_HWOR,       8,      "hardware OR patch applied")	\
+_ELF_DEFINE_ODK(ODK_GP_GROUP,   9,					\
+	"GP group to use for text/data sections")			\
+_ELF_DEFINE_ODK(ODK_IDENT,      10,     "ID information")		\
+_ELF_DEFINE_ODK(ODK_PAGESIZE,   11,     "page size information")
+
+#undef	_ELF_DEFINE_ODK
+#define	_ELF_DEFINE_ODK(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_OPTION_KINDS()
+	ODK__LAST__
+};
+
+/*
+ * ODK_EXCEPTIONS info field masks.
+ */
+
+#define	_ELF_DEFINE_ODK_EXCEPTIONS_MASK()				\
+_ELF_DEFINE_OEX(OEX_FPU_MIN,    0x0000001FUL,				\
+	"minimum FPU exception which must be enabled")			\
+_ELF_DEFINE_OEX(OEX_FPU_MAX,    0x00001F00UL,				\
+	"maximum FPU exception which can be enabled")			\
+_ELF_DEFINE_OEX(OEX_PAGE0,      0x00010000UL,				\
+	"page zero must be mapped")					\
+_ELF_DEFINE_OEX(OEX_SMM,        0x00020000UL,				\
+	"run in sequential memory mode")				\
+_ELF_DEFINE_OEX(OEX_PRECISEFP,  0x00040000UL,				\
+	"run in precise FP exception mode")				\
+_ELF_DEFINE_OEX(OEX_DISMISS,    0x00080000UL,				\
+	"dismiss invalid address traps")
+
+#undef	_ELF_DEFINE_OEX
+#define	_ELF_DEFINE_OEX(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_ODK_EXCEPTIONS_MASK()
+	OEX__LAST__
+};
+
+/*
+ * ODK_PAD info field masks.
+ */
+
+#define	_ELF_DEFINE_ODK_PAD_MASK()					\
+_ELF_DEFINE_OPAD(OPAD_PREFIX,   0x0001)					\
+_ELF_DEFINE_OPAD(OPAD_POSTFIX,  0x0002)					\
+_ELF_DEFINE_OPAD(OPAD_SYMBOL,   0x0004)
+
+#undef	_ELF_DEFINE_OPAD
+#define	_ELF_DEFINE_OPAD(N, V)		N = V ,
+enum {
+	_ELF_DEFINE_ODK_PAD_MASK()
+	OPAD__LAST__
+};
+
+/*
+ * ODK_HWPATCH info field masks.
+ */
+
+#define	_ELF_DEFINE_ODK_HWPATCH_MASK()					\
+_ELF_DEFINE_OHW(OHW_R4KEOP,     0x00000001UL,				\
+	"patch for R4000 branch at end-of-page bug")			\
+_ELF_DEFINE_OHW(OHW_R8KPFETCH,  0x00000002UL,				\
+	"R8000 prefetch bug may occur")					\
+_ELF_DEFINE_OHW(OHW_R5KEOP,     0x00000004UL,				\
+	"patch for R5000 branch at end-of-page bug")			\
+_ELF_DEFINE_OHW(OHW_R5KCVTL,    0x00000008UL,				\
+	"R5000 cvt.[ds].l bug: clean == 1")				\
+_ELF_DEFINE_OHW(OHW_R10KLDL,    0x00000010UL,				\
+	"needd patch for R10000 misaligned load")
+
+#undef	_ELF_DEFINE_OHW
+#define	_ELF_DEFINE_OHW(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_ODK_HWPATCH_MASK()
+	OHW__LAST__
+};
+
+/*
+ * ODK_HWAND/ODK_HWOR info field and hwp_flags[12] masks.
+ */
+
+#define	_ELF_DEFINE_ODK_HWP_MASK()					\
+_ELF_DEFINE_HWP(OHWA0_R4KEOP_CHECKED, 0x00000001UL,			\
+	"object checked for R4000 end-of-page bug")			\
+_ELF_DEFINE_HWP(OHWA0_R4KEOP_CLEAN, 0x00000002UL,			\
+	"object verified clean for R4000 end-of-page bug")		\
+_ELF_DEFINE_HWP(OHWO0_FIXADE,   0x00000001UL,				\
+	"object requires call to fixade")
+
+#undef	_ELF_DEFINE_HWP
+#define	_ELF_DEFINE_HWP(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_ODK_HWP_MASK()
+	OHWX0__LAST__
+};
+
+/*
+ * ODK_IDENT/ODK_GP_GROUP info field masks.
+ */
+
+#define	_ELF_DEFINE_ODK_GP_MASK()					\
+_ELF_DEFINE_OGP(OGP_GROUP,      0x0000FFFFUL, "GP group number")	\
+_ELF_DEFINE_OGP(OGP_SELF,       0x00010000UL,				\
+	"GP group is self-contained")
+
+#undef	_ELF_DEFINE_OGP
+#define	_ELF_DEFINE_OGP(N, V, DESCR)	N = V ,
+enum {
+	_ELF_DEFINE_ODK_GP_MASK()
+	OGP__LAST__
+};
+
+/*
+ * MIPS ELF register info descriptor.
+ */
+
+/* 32 bit RegInfo entry. */
+typedef struct {
+	Elf32_Word	ri_gprmask;  /* Mask of general register used. */
+	Elf32_Word	ri_cprmask[4]; /* Mask of coprocessor register used. */
+	Elf32_Addr	ri_gp_value; /* GP register value. */
+} Elf32_RegInfo;
+
+/* 64 bit RegInfo entry. */
+typedef struct {
+	Elf64_Word	ri_gprmask;  /* Mask of general register used. */
+	Elf64_Word	ri_pad;	     /* Padding. */
+	Elf64_Word	ri_cprmask[4]; /* Mask of coprocessor register used. */
+	Elf64_Addr	ri_gp_value; /* GP register value. */
+} Elf64_RegInfo;
+
+/*
+ * Program Header Table (PHDR) entries.
+ */
+
+/* 32 bit PHDR entry. */
+typedef struct {
+	Elf32_Word	p_type;	     /* Type of segment. */
+	Elf32_Off	p_offset;    /* File offset to segment. */
+	Elf32_Addr	p_vaddr;     /* Virtual address in memory. */
+	Elf32_Addr	p_paddr;     /* Physical address (if relevant). */
+	Elf32_Word	p_filesz;    /* Size of segment in file. */
+	Elf32_Word	p_memsz;     /* Size of segment in memory. */
+	Elf32_Word	p_flags;     /* Segment flags. */
+	Elf32_Word	p_align;     /* Alignment constraints. */
+} Elf32_Phdr;
+
+/* 64 bit PHDR entry. */
+typedef struct {
+	Elf64_Word	p_type;	     /* Type of segment. */
+	Elf64_Word	p_flags;     /* Segment flags. */
+	Elf64_Off	p_offset;    /* File offset to segment. */
+	Elf64_Addr	p_vaddr;     /* Virtual address in memory. */
+	Elf64_Addr	p_paddr;     /* Physical address (if relevant). */
+	Elf64_Xword	p_filesz;    /* Size of segment in file. */
+	Elf64_Xword	p_memsz;     /* Size of segment in memory. */
+	Elf64_Xword	p_align;     /* Alignment constraints. */
+} Elf64_Phdr;
+
+
+/*
+ * Move entries, for describing data in COMMON blocks in a compact
+ * manner.
+ */
+
+/* 32-bit move entry. */
+typedef struct {
+	Elf32_Lword	m_value;     /* Initialization value. */
+	Elf32_Word 	m_info;	     /* Encoded size and index. */
+	Elf32_Word	m_poffset;   /* Offset relative to symbol. */
+	Elf32_Half	m_repeat;    /* Repeat count. */
+	Elf32_Half	m_stride;    /* Number of units to skip. */
+} Elf32_Move;
+
+/* 64-bit move entry. */
+typedef struct {
+	Elf64_Lword	m_value;     /* Initialization value. */
+	Elf64_Xword 	m_info;	     /* Encoded size and index. */
+	Elf64_Xword	m_poffset;   /* Offset relative to symbol. */
+	Elf64_Half	m_repeat;    /* Repeat count. */
+	Elf64_Half	m_stride;    /* Number of units to skip. */
+} Elf64_Move;
+
+#define ELF32_M_SYM(I)		((I) >> 8)
+#define ELF32_M_SIZE(I)		((unsigned char) (I))
+#define ELF32_M_INFO(M, S)	(((M) << 8) + (unsigned char) (S))
+
+#define ELF64_M_SYM(I)		((I) >> 8)
+#define ELF64_M_SIZE(I)		((unsigned char) (I))
+#define ELF64_M_INFO(M, S)	(((M) << 8) + (unsigned char) (S))
+
+/*
+ * Section Header Table (SHDR) entries.
+ */
+
+/* 32 bit SHDR */
+typedef struct {
+	Elf32_Word	sh_name;     /* index of section name */
+	Elf32_Word	sh_type;     /* section type */
+	Elf32_Word	sh_flags;    /* section flags */
+	Elf32_Addr	sh_addr;     /* in-memory address of section */
+	Elf32_Off	sh_offset;   /* file offset of section */
+	Elf32_Word	sh_size;     /* section size in bytes */
+	Elf32_Word	sh_link;     /* section header table link */
+	Elf32_Word	sh_info;     /* extra information */
+	Elf32_Word	sh_addralign; /* alignment constraint */
+	Elf32_Word	sh_entsize;   /* size for fixed-size entries */
+} Elf32_Shdr;
+
+/* 64 bit SHDR */
+typedef struct {
+	Elf64_Word	sh_name;     /* index of section name */
+	Elf64_Word	sh_type;     /* section type */
+	Elf64_Xword	sh_flags;    /* section flags */
+	Elf64_Addr	sh_addr;     /* in-memory address of section */
+	Elf64_Off	sh_offset;   /* file offset of section */
+	Elf64_Xword	sh_size;     /* section size in bytes */
+	Elf64_Word	sh_link;     /* section header table link */
+	Elf64_Word	sh_info;     /* extra information */
+	Elf64_Xword	sh_addralign; /* alignment constraint */
+	Elf64_Xword	sh_entsize;  /* size for fixed-size entries */
+} Elf64_Shdr;
+
+
+/*
+ * Symbol table entries.
+ */
+
+typedef struct {
+	Elf32_Word	st_name;     /* index of symbol's name */
+	Elf32_Addr	st_value;    /* value for the symbol */
+	Elf32_Word	st_size;     /* size of associated data */
+	unsigned char	st_info;     /* type and binding attributes */
+	unsigned char	st_other;    /* visibility */
+	Elf32_Half	st_shndx;    /* index of related section */
+} Elf32_Sym;
+
+typedef struct {
+	Elf64_Word	st_name;     /* index of symbol's name */
+	unsigned char	st_info;     /* type and binding attributes */
+	unsigned char	st_other;    /* visibility */
+	Elf64_Half	st_shndx;    /* index of related section */
+	Elf64_Addr	st_value;    /* value for the symbol */
+	Elf64_Xword	st_size;     /* size of associated data */
+} Elf64_Sym;
+
+#define ELF32_ST_BIND(I)	((I) >> 4)
+#define ELF32_ST_TYPE(I)	((I) & 0xFU)
+#define ELF32_ST_INFO(B,T)	(((B) << 4) + ((T) & 0xF))
+
+#define ELF64_ST_BIND(I)	((I) >> 4)
+#define ELF64_ST_TYPE(I)	((I) & 0xFU)
+#define ELF64_ST_INFO(B,T)	(((B) << 4) + ((T) & 0xF))
+
+#define ELF32_ST_VISIBILITY(O)	((O) & 0x3)
+#define ELF64_ST_VISIBILITY(O)	((O) & 0x3)
+
+/*
+ * Syminfo descriptors, containing additional symbol information.
+ */
+
+/* 32-bit entry. */
+typedef struct {
+	Elf32_Half	si_boundto;  /* Entry index with additional flags. */
+	Elf32_Half	si_flags;    /* Flags. */
+} Elf32_Syminfo;
+
+/* 64-bit entry. */
+typedef struct {
+	Elf64_Half	si_boundto;  /* Entry index with additional flags. */
+	Elf64_Half	si_flags;    /* Flags. */
+} Elf64_Syminfo;
+
+/*
+ * Relocation descriptors.
+ */
+
+typedef struct {
+	Elf32_Addr	r_offset;    /* location to apply relocation to */
+	Elf32_Word	r_info;	     /* type+section for relocation */
+} Elf32_Rel;
+
+typedef struct {
+	Elf32_Addr	r_offset;    /* location to apply relocation to */
+	Elf32_Word	r_info;      /* type+section for relocation */
+	Elf32_Sword	r_addend;    /* constant addend */
+} Elf32_Rela;
+
+typedef struct {
+	Elf64_Addr	r_offset;    /* location to apply relocation to */
+	Elf64_Xword	r_info;      /* type+section for relocation */
+} Elf64_Rel;
+
+typedef struct {
+	Elf64_Addr	r_offset;    /* location to apply relocation to */
+	Elf64_Xword	r_info;      /* type+section for relocation */
+	Elf64_Sxword	r_addend;    /* constant addend */
+} Elf64_Rela;
+
+
+#define ELF32_R_SYM(I)		((I) >> 8)
+#define ELF32_R_TYPE(I)		((unsigned char) (I))
+#define ELF32_R_INFO(S,T)	(((S) << 8) + (unsigned char) (T))
+
+#define ELF64_R_SYM(I)		((I) >> 32)
+#define ELF64_R_TYPE(I)		((I) & 0xFFFFFFFFUL)
+#define ELF64_R_INFO(S,T)	(((S) << 32) + ((T) & 0xFFFFFFFFUL))
+
+/*
+ * Symbol versioning structures.
+ */
+
+/* 32-bit structures. */
+typedef struct
+{
+	Elf32_Word	vda_name;    /* Index to name. */
+	Elf32_Word	vda_next;    /* Offset to next entry. */
+} Elf32_Verdaux;
+
+typedef struct
+{
+	Elf32_Word	vna_hash;    /* Hash value of dependency name. */
+	Elf32_Half	vna_flags;   /* Flags. */
+	Elf32_Half	vna_other;   /* Unused. */
+	Elf32_Word	vna_name;    /* Offset to dependency name. */
+	Elf32_Word	vna_next;    /* Offset to next vernaux entry. */
+} Elf32_Vernaux;
+
+typedef struct
+{
+	Elf32_Half	vd_version;  /* Version information. */
+	Elf32_Half	vd_flags;    /* Flags. */
+	Elf32_Half	vd_ndx;	     /* Index into the versym section. */
+	Elf32_Half	vd_cnt;	     /* Number of aux entries. */
+	Elf32_Word	vd_hash;     /* Hash value of name. */
+	Elf32_Word	vd_aux;	     /* Offset to aux entries. */
+	Elf32_Word	vd_next;     /* Offset to next version definition. */
+} Elf32_Verdef;
+
+typedef struct
+{
+	Elf32_Half	vn_version;  /* Version number. */
+	Elf32_Half	vn_cnt;	     /* Number of aux entries. */
+	Elf32_Word	vn_file;     /* Offset of associated file name. */
+	Elf32_Word	vn_aux;	     /* Offset of vernaux array. */
+	Elf32_Word	vn_next;     /* Offset of next verneed entry. */
+} Elf32_Verneed;
+
+typedef Elf32_Half	Elf32_Versym;
+
+/* 64-bit structures. */
+
+typedef struct {
+	Elf64_Word	vda_name;    /* Index to name. */
+	Elf64_Word	vda_next;    /* Offset to next entry. */
+} Elf64_Verdaux;
+
+typedef struct {
+	Elf64_Word	vna_hash;    /* Hash value of dependency name. */
+	Elf64_Half	vna_flags;   /* Flags. */
+	Elf64_Half	vna_other;   /* Unused. */
+	Elf64_Word	vna_name;    /* Offset to dependency name. */
+	Elf64_Word	vna_next;    /* Offset to next vernaux entry. */
+} Elf64_Vernaux;
+
+typedef struct {
+	Elf64_Half	vd_version;  /* Version information. */
+	Elf64_Half	vd_flags;    /* Flags. */
+	Elf64_Half	vd_ndx;	     /* Index into the versym section. */
+	Elf64_Half	vd_cnt;	     /* Number of aux entries. */
+	Elf64_Word	vd_hash;     /* Hash value of name. */
+	Elf64_Word	vd_aux;	     /* Offset to aux entries. */
+	Elf64_Word	vd_next;     /* Offset to next version definition. */
+} Elf64_Verdef;
+
+typedef struct {
+	Elf64_Half	vn_version;  /* Version number. */
+	Elf64_Half	vn_cnt;	     /* Number of aux entries. */
+	Elf64_Word	vn_file;     /* Offset of associated file name. */
+	Elf64_Word	vn_aux;	     /* Offset of vernaux array. */
+	Elf64_Word	vn_next;     /* Offset of next verneed entry. */
+} Elf64_Verneed;
+
+typedef Elf64_Half	Elf64_Versym;
+
+
+/*
+ * The header for GNU-style hash sections.
+ */
+
+typedef struct {
+	uint32_t	gh_nbuckets;	/* Number of hash buckets. */
+	uint32_t	gh_symndx;	/* First visible symbol in .dynsym. */
+	uint32_t	gh_maskwords;	/* #maskwords used in bloom filter. */
+	uint32_t	gh_shift2;	/* Bloom filter shift count. */
+} Elf_GNU_Hash_Header;
+
+#endif	/* _ELFDEFINITIONS_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/common/native-elf-format	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,49 @@
+#!/bin/sh
+#
+# $Id: native-elf-format 3293 2016-01-07 19:26:27Z emaste $
+#
+# Find the native ELF format for a host platform by compiling a
+# test object and examining the resulting object.
+#
+# This script is used if there is no easy way to determine this
+# information statically at compile time.
+
+program=`basename $0`
+tmp_c=`mktemp -u nefXXXXXX`.c
+tmp_o=`echo ${tmp_c} | sed -e 's/.c$/.o/'`
+
+trap "rm -f ${tmp_c} ${tmp_o}"	0 1 2 3 15
+
+touch ${tmp_c}
+
+echo "/* Generated by ${program} on `date` */"
+
+cc -c ${tmp_c} -o ${tmp_o}
+LC_ALL=C readelf -h ${tmp_o} | awk '
+$1 ~ "Class:" {
+        sub("ELF","",$2); elfclass = $2;
+    }
+$1 ~ "Data:"  {
+        if (match($0, "little")) {
+            elfdata = "LSB";
+ 	} else {
+            elfdata = "MSB";
+	}
+    }
+$1 ~ "Machine:" {
+        if (match($0, "Intel.*386")) {
+            elfarch = "EM_386";
+        } else if (match($0, "MIPS")) {
+            elfarch = "EM_MIPS";
+        } else if (match($0, ".*[xX]86-64")) {
+            elfarch = "EM_X86_64";
+        } else {
+            elfarch = "unknown";
+        }
+    }
+END {
+    printf("#define	ELFTC_CLASS	ELFCLASS%s\n", elfclass);
+    printf("#define	ELFTC_ARCH	%s\n", elfarch);
+    printf("#define	ELFTC_BYTEORDER	ELFDATA2%s\n", elfdata);
+}'
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/common/os.Linux.mk	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,15 @@
+#
+# Build recipes for Linux based operating systems.
+#
+# $Id: os.Linux.mk 3594 2018-04-11 18:26:50Z jkoshy $
+
+_NATIVE_ELF_FORMAT = native-elf-format
+
+.if !make(obj)
+.BEGIN:	${.OBJDIR}/${_NATIVE_ELF_FORMAT}.h
+
+${.OBJDIR}/${_NATIVE_ELF_FORMAT}.h:
+	${.CURDIR}/${_NATIVE_ELF_FORMAT} > ${.TARGET} || rm ${.TARGET}
+.endif
+
+CLEANFILES += ${.OBJDIR}/${_NATIVE_ELF_FORMAT}.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/common/utarray.h	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,237 @@
+/*
+Copyright (c) 2008-2013, Troy D. Hanson   http://uthash.sourceforge.net
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* $Id: utarray.h 2694 2012-11-24 17:11:58Z kaiwang27 $ */
+
+/* a dynamic array implementation using macros 
+ * see http://uthash.sourceforge.net/utarray
+ */
+#ifndef UTARRAY_H
+#define UTARRAY_H
+
+#define UTARRAY_VERSION 1.9.7
+
+#ifdef __GNUC__
+#define _UNUSED_ __attribute__ ((__unused__)) 
+#else
+#define _UNUSED_ 
+#endif
+
+#include <stddef.h>  /* size_t */
+#include <string.h>  /* memset, etc */
+#include <stdlib.h>  /* exit */
+
+#ifndef oom
+#define oom() exit(-1)
+#endif
+
+typedef void (ctor_f)(void *dst, const void *src);
+typedef void (dtor_f)(void *elt);
+typedef void (init_f)(void *elt);
+typedef struct {
+    size_t sz;
+    init_f *init;
+    ctor_f *copy;
+    dtor_f *dtor;
+} UT_icd;
+
+typedef struct {
+    unsigned i,n;/* i: index of next available slot, n: num slots */
+    UT_icd icd;  /* initializer, copy and destructor functions */
+    char *d;     /* n slots of size icd->sz*/
+} UT_array;
+
+#define utarray_init(a,_icd) do {                                             \
+  memset(a,0,sizeof(UT_array));                                               \
+  (a)->icd=*_icd;                                                             \
+} while(0)
+
+#define utarray_done(a) do {                                                  \
+  if ((a)->n) {                                                               \
+    if ((a)->icd.dtor) {                                                      \
+      size_t _ut_i;                                                           \
+      for(_ut_i=0; _ut_i < (a)->i; _ut_i++) {                                 \
+        (a)->icd.dtor(utarray_eltptr(a,_ut_i));                               \
+      }                                                                       \
+    }                                                                         \
+    free((a)->d);                                                             \
+  }                                                                           \
+  (a)->n=0;                                                                   \
+} while(0)
+
+#define utarray_new(a,_icd) do {                                              \
+  a=(UT_array*)malloc(sizeof(UT_array));                                      \
+  utarray_init(a,_icd);                                                       \
+} while(0)
+
+#define utarray_free(a) do {                                                  \
+  utarray_done(a);                                                            \
+  free(a);                                                                    \
+} while(0)
+
+#define utarray_reserve(a,by) do {                                            \
+  if (((a)->i+by) > ((a)->n)) {                                               \
+    while(((a)->i+by) > ((a)->n)) { (a)->n = ((a)->n ? (2*(a)->n) : 8); }     \
+    if ( ((a)->d=(char*)realloc((a)->d, (a)->n*(a)->icd.sz)) == NULL) oom();  \
+  }                                                                           \
+} while(0)
+
+#define utarray_push_back(a,p) do {                                           \
+  utarray_reserve(a,1);                                                       \
+  if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,(a)->i++), p); }      \
+  else { memcpy(_utarray_eltptr(a,(a)->i++), p, (a)->icd.sz); };              \
+} while(0)
+
+#define utarray_pop_back(a) do {                                              \
+  if ((a)->icd.dtor) { (a)->icd.dtor( _utarray_eltptr(a,--((a)->i))); }       \
+  else { (a)->i--; }                                                          \
+} while(0)
+
+#define utarray_extend_back(a) do {                                           \
+  utarray_reserve(a,1);                                                       \
+  if ((a)->icd.init) { (a)->icd.init(_utarray_eltptr(a,(a)->i)); }            \
+  else { memset(_utarray_eltptr(a,(a)->i),0,(a)->icd.sz); }                   \
+  (a)->i++;                                                                   \
+} while(0)
+
+#define utarray_len(a) ((a)->i)
+
+#define utarray_eltptr(a,j) (((j) < (a)->i) ? _utarray_eltptr(a,j) : NULL)
+#define _utarray_eltptr(a,j) ((char*)((a)->d + ((a)->icd.sz*(j) )))
+
+#define utarray_insert(a,p,j) do {                                            \
+  utarray_reserve(a,1);                                                       \
+  if (j > (a)->i) break;                                                      \
+  if ((j) < (a)->i) {                                                         \
+    memmove( _utarray_eltptr(a,(j)+1), _utarray_eltptr(a,j),                  \
+             ((a)->i - (j))*((a)->icd.sz));                                   \
+  }                                                                           \
+  if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,j), p); }             \
+  else { memcpy(_utarray_eltptr(a,j), p, (a)->icd.sz); };                     \
+  (a)->i++;                                                                   \
+} while(0)
+
+#define utarray_inserta(a,w,j) do {                                           \
+  if (utarray_len(w) == 0) break;                                             \
+  if (j > (a)->i) break;                                                      \
+  utarray_reserve(a,utarray_len(w));                                          \
+  if ((j) < (a)->i) {                                                         \
+    memmove(_utarray_eltptr(a,(j)+utarray_len(w)),                            \
+            _utarray_eltptr(a,j),                                             \
+            ((a)->i - (j))*((a)->icd.sz));                                    \
+  }                                                                           \
+  if ((a)->icd.copy) {                                                        \
+    size_t _ut_i;                                                             \
+    for(_ut_i=0;_ut_i<(w)->i;_ut_i++) {                                       \
+      (a)->icd.copy(_utarray_eltptr(a,j+_ut_i), _utarray_eltptr(w,_ut_i));    \
+    }                                                                         \
+  } else {                                                                    \
+    memcpy(_utarray_eltptr(a,j), _utarray_eltptr(w,0),                        \
+           utarray_len(w)*((a)->icd.sz));                                     \
+  }                                                                           \
+  (a)->i += utarray_len(w);                                                   \
+} while(0)
+
+#define utarray_resize(dst,num) do {                                          \
+  size_t _ut_i;                                                               \
+  if (dst->i > (size_t)(num)) {                                               \
+    if ((dst)->icd.dtor) {                                                    \
+      for(_ut_i=num; _ut_i < dst->i; _ut_i++) {                               \
+        (dst)->icd.dtor(utarray_eltptr(dst,_ut_i));                           \
+      }                                                                       \
+    }                                                                         \
+  } else if (dst->i < (size_t)(num)) {                                        \
+    utarray_reserve(dst,num-dst->i);                                          \
+    if ((dst)->icd.init) {                                                    \
+      for(_ut_i=dst->i; _ut_i < num; _ut_i++) {                               \
+        (dst)->icd.init(utarray_eltptr(dst,_ut_i));                           \
+      }                                                                       \
+    } else {                                                                  \
+      memset(_utarray_eltptr(dst,dst->i),0,(dst)->icd.sz*(num-dst->i));       \
+    }                                                                         \
+  }                                                                           \
+  dst->i = num;                                                               \
+} while(0)
+
+#define utarray_concat(dst,src) do {                                          \
+  utarray_inserta((dst),(src),utarray_len(dst));                              \
+} while(0)
+
+#define utarray_erase(a,pos,len) do {                                         \
+  if ((a)->icd.dtor) {                                                        \
+    size_t _ut_i;                                                             \
+    for(_ut_i=0; _ut_i < len; _ut_i++) {                                      \
+      (a)->icd.dtor(utarray_eltptr((a),pos+_ut_i));                           \
+    }                                                                         \
+  }                                                                           \
+  if ((a)->i > (pos+len)) {                                                   \
+    memmove( _utarray_eltptr((a),pos), _utarray_eltptr((a),pos+len),          \
+            (((a)->i)-(pos+len))*((a)->icd.sz));                              \
+  }                                                                           \
+  (a)->i -= (len);                                                            \
+} while(0)
+
+#define utarray_renew(a,u) do {                                               \
+  if (a) utarray_clear(a); \
+  else utarray_new((a),(u));   \
+} while(0) 
+
+#define utarray_clear(a) do {                                                 \
+  if ((a)->i > 0) {                                                           \
+    if ((a)->icd.dtor) {                                                      \
+      size_t _ut_i;                                                           \
+      for(_ut_i=0; _ut_i < (a)->i; _ut_i++) {                                 \
+        (a)->icd.dtor(utarray_eltptr(a,_ut_i));                               \
+      }                                                                       \
+    }                                                                         \
+    (a)->i = 0;                                                               \
+  }                                                                           \
+} while(0)
+
+#define utarray_sort(a,cmp) do {                                              \
+  qsort((a)->d, (a)->i, (a)->icd.sz, cmp);                                    \
+} while(0)
+
+#define utarray_find(a,v,cmp) bsearch((v),(a)->d,(a)->i,(a)->icd.sz,cmp)
+
+#define utarray_front(a) (((a)->i) ? (_utarray_eltptr(a,0)) : NULL)
+#define utarray_next(a,e) (((e)==NULL) ? utarray_front(a) : (((int)((a)->i) > (utarray_eltidx(a,e)+1)) ? _utarray_eltptr(a,utarray_eltidx(a,e)+1) : NULL))
+#define utarray_prev(a,e) (((e)==NULL) ? utarray_back(a) : ((utarray_eltidx(a,e) > 0) ? _utarray_eltptr(a,utarray_eltidx(a,e)-1) : NULL))
+#define utarray_back(a) (((a)->i) ? (_utarray_eltptr(a,(a)->i-1)) : NULL)
+#define utarray_eltidx(a,e) (((char*)(e) >= (char*)((a)->d)) ? (int)(((char*)(e) - (char*)((a)->d))/(a)->icd.sz) : -1)
+
+/* last we pre-define a few icd for common utarrays of ints and strings */
+static void utarray_str_cpy(void *dst, const void *src) {
+  char *const*_src = (char*const*)src, **_dst = (char**)dst;
+  *_dst = (*_src == NULL) ? NULL : strdup(*_src);
+}
+static void utarray_str_dtor(void *elt) {
+  char **eltc = (char**)elt;
+  if (*eltc) free(*eltc);
+}
+static const UT_icd ut_str_icd _UNUSED_ = {sizeof(char*),NULL,utarray_str_cpy,utarray_str_dtor};
+static const UT_icd ut_int_icd _UNUSED_ = {sizeof(int),NULL,NULL,NULL};
+static const UT_icd ut_ptr_icd _UNUSED_ = {sizeof(void*),NULL,NULL,NULL};
+
+
+#endif /* UTARRAY_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/common/uthash.h	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,919 @@
+/*
+Copyright (c) 2003-2013, Troy D. Hanson     http://uthash.sourceforge.net
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* $Id: uthash.h 2682 2012-11-23 22:04:22Z kaiwang27 $ */
+
+#ifndef UTHASH_H
+#define UTHASH_H 
+
+#include <string.h>   /* memcmp,strlen */
+#include <stddef.h>   /* ptrdiff_t */
+#include <stdlib.h>   /* exit() */
+
+/* These macros use decltype or the earlier __typeof GNU extension.
+   As decltype is only available in newer compilers (VS2010 or gcc 4.3+
+   when compiling c++ source) this code uses whatever method is needed
+   or, for VS2008 where neither is available, uses casting workarounds. */
+#ifdef _MSC_VER         /* MS compiler */
+#if _MSC_VER >= 1600 && defined(__cplusplus)  /* VS2010 or newer in C++ mode */
+#define DECLTYPE(x) (decltype(x))
+#else                   /* VS2008 or older (or VS2010 in C mode) */
+#define NO_DECLTYPE
+#define DECLTYPE(x)
+#endif
+#else                   /* GNU, Sun and other compilers */
+#define DECLTYPE(x) (__typeof(x))
+#endif
+
+#ifdef NO_DECLTYPE
+#define DECLTYPE_ASSIGN(dst,src)                                                 \
+do {                                                                             \
+  char **_da_dst = (char**)(&(dst));                                             \
+  *_da_dst = (char*)(src);                                                       \
+} while(0)
+#else 
+#define DECLTYPE_ASSIGN(dst,src)                                                 \
+do {                                                                             \
+  (dst) = DECLTYPE(dst)(src);                                                    \
+} while(0)
+#endif
+
+/* a number of the hash function use uint32_t which isn't defined on win32 */
+#ifdef _MSC_VER
+typedef unsigned int uint32_t;
+typedef unsigned char uint8_t;
+#else
+#include <inttypes.h>   /* uint32_t */
+#endif
+
+#define UTHASH_VERSION 1.9.7
+
+#ifndef uthash_fatal
+#define uthash_fatal(msg) exit(-1)        /* fatal error (out of memory,etc) */
+#endif
+#ifndef uthash_malloc
+#define uthash_malloc(sz) malloc(sz)      /* malloc fcn                      */
+#endif
+#ifndef uthash_free
+#define uthash_free(ptr,sz) free(ptr)     /* free fcn                        */
+#endif
+
+#ifndef uthash_noexpand_fyi
+#define uthash_noexpand_fyi(tbl)          /* can be defined to log noexpand  */
+#endif
+#ifndef uthash_expand_fyi
+#define uthash_expand_fyi(tbl)            /* can be defined to log expands   */
+#endif
+
+/* initial number of buckets */
+#define HASH_INITIAL_NUM_BUCKETS 32      /* initial number of buckets        */
+#define HASH_INITIAL_NUM_BUCKETS_LOG2 5  /* lg2 of initial number of buckets */
+#define HASH_BKT_CAPACITY_THRESH 10      /* expand when bucket count reaches */
+
+/* calculate the element whose hash handle address is hhe */
+#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
+
+#define HASH_FIND(hh,head,keyptr,keylen,out)                                     \
+do {                                                                             \
+  unsigned _hf_bkt,_hf_hashv;                                                    \
+  out=NULL;                                                                      \
+  if (head) {                                                                    \
+     HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt);   \
+     if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) {                           \
+       HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ],  \
+                        keyptr,keylen,out);                                      \
+     }                                                                           \
+  }                                                                              \
+} while (0)
+
+#ifdef HASH_BLOOM
+#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM)
+#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0)
+#define HASH_BLOOM_MAKE(tbl)                                                     \
+do {                                                                             \
+  (tbl)->bloom_nbits = HASH_BLOOM;                                               \
+  (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN);                 \
+  if (!((tbl)->bloom_bv))  { uthash_fatal( "out of memory"); }                   \
+  memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN);                                \
+  (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE;                                       \
+} while (0) 
+
+#define HASH_BLOOM_FREE(tbl)                                                     \
+do {                                                                             \
+  uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN);                              \
+} while (0) 
+
+#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8)))
+#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8)))
+
+#define HASH_BLOOM_ADD(tbl,hashv)                                                \
+  HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
+
+#define HASH_BLOOM_TEST(tbl,hashv)                                               \
+  HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
+
+#else
+#define HASH_BLOOM_MAKE(tbl) 
+#define HASH_BLOOM_FREE(tbl) 
+#define HASH_BLOOM_ADD(tbl,hashv) 
+#define HASH_BLOOM_TEST(tbl,hashv) (1)
+#endif
+
+#define HASH_MAKE_TABLE(hh,head)                                                 \
+do {                                                                             \
+  (head)->hh.tbl = (UT_hash_table*)uthash_malloc(                                \
+                  sizeof(UT_hash_table));                                        \
+  if (!((head)->hh.tbl))  { uthash_fatal( "out of memory"); }                    \
+  memset((head)->hh.tbl, 0, sizeof(UT_hash_table));                              \
+  (head)->hh.tbl->tail = &((head)->hh);                                          \
+  (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS;                        \
+  (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2;              \
+  (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head);                    \
+  (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc(                      \
+          HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket));               \
+  if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); }             \
+  memset((head)->hh.tbl->buckets, 0,                                             \
+          HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket));               \
+  HASH_BLOOM_MAKE((head)->hh.tbl);                                               \
+  (head)->hh.tbl->signature = HASH_SIGNATURE;                                    \
+} while(0)
+
+#define HASH_ADD(hh,head,fieldname,keylen_in,add)                                \
+        HASH_ADD_KEYPTR(hh,head,&((add)->fieldname),keylen_in,add)
+ 
+#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add)                            \
+do {                                                                             \
+ unsigned _ha_bkt;                                                               \
+ (add)->hh.next = NULL;                                                          \
+ (add)->hh.key = (char*)keyptr;                                                  \
+ (add)->hh.keylen = (unsigned)keylen_in;                                                   \
+ if (!(head)) {                                                                  \
+    head = (add);                                                                \
+    (head)->hh.prev = NULL;                                                      \
+    HASH_MAKE_TABLE(hh,head);                                                    \
+ } else {                                                                        \
+    (head)->hh.tbl->tail->next = (add);                                          \
+    (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail);         \
+    (head)->hh.tbl->tail = &((add)->hh);                                         \
+ }                                                                               \
+ (head)->hh.tbl->num_items++;                                                    \
+ (add)->hh.tbl = (head)->hh.tbl;                                                 \
+ HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets,                         \
+         (add)->hh.hashv, _ha_bkt);                                              \
+ HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh);                   \
+ HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv);                                 \
+ HASH_EMIT_KEY(hh,head,keyptr,keylen_in);                                        \
+ HASH_FSCK(hh,head);                                                             \
+} while(0)
+
+#define HASH_TO_BKT( hashv, num_bkts, bkt )                                      \
+do {                                                                             \
+  bkt = ((hashv) & ((num_bkts) - 1));                                            \
+} while(0)
+
+/* delete "delptr" from the hash table.
+ * "the usual" patch-up process for the app-order doubly-linked-list.
+ * The use of _hd_hh_del below deserves special explanation.
+ * These used to be expressed using (delptr) but that led to a bug
+ * if someone used the same symbol for the head and deletee, like
+ *  HASH_DELETE(hh,users,users);
+ * We want that to work, but by changing the head (users) below
+ * we were forfeiting our ability to further refer to the deletee (users)
+ * in the patch-up process. Solution: use scratch space to
+ * copy the deletee pointer, then the latter references are via that
+ * scratch pointer rather than through the repointed (users) symbol.
+ */
+#define HASH_DELETE(hh,head,delptr)                                              \
+do {                                                                             \
+    unsigned _hd_bkt;                                                            \
+    struct UT_hash_handle *_hd_hh_del;                                           \
+    if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) )  {         \
+        uthash_free((head)->hh.tbl->buckets,                                     \
+                    (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
+        HASH_BLOOM_FREE((head)->hh.tbl);                                         \
+        uthash_free((head)->hh.tbl, sizeof(UT_hash_table));                      \
+        head = NULL;                                                             \
+    } else {                                                                     \
+        _hd_hh_del = &((delptr)->hh);                                            \
+        if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) {     \
+            (head)->hh.tbl->tail =                                               \
+                (UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) +               \
+                (head)->hh.tbl->hho);                                            \
+        }                                                                        \
+        if ((delptr)->hh.prev) {                                                 \
+            ((UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) +                  \
+                    (head)->hh.tbl->hho))->next = (delptr)->hh.next;             \
+        } else {                                                                 \
+            DECLTYPE_ASSIGN(head,(delptr)->hh.next);                             \
+        }                                                                        \
+        if (_hd_hh_del->next) {                                                  \
+            ((UT_hash_handle*)((ptrdiff_t)_hd_hh_del->next +                     \
+                    (head)->hh.tbl->hho))->prev =                                \
+                    _hd_hh_del->prev;                                            \
+        }                                                                        \
+        HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt);   \
+        HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del);        \
+        (head)->hh.tbl->num_items--;                                             \
+    }                                                                            \
+    HASH_FSCK(hh,head);                                                          \
+} while (0)
+
+
+/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
+#define HASH_FIND_STR(head,findstr,out)                                          \
+    HASH_FIND(hh,head,findstr,strlen(findstr),out)
+#define HASH_ADD_STR(head,strfield,add)                                          \
+    HASH_ADD(hh,head,strfield,strlen(add->strfield),add)
+#define HASH_FIND_INT(head,findint,out)                                          \
+    HASH_FIND(hh,head,findint,sizeof(int),out)
+#define HASH_ADD_INT(head,intfield,add)                                          \
+    HASH_ADD(hh,head,intfield,sizeof(int),add)
+#define HASH_FIND_PTR(head,findptr,out)                                          \
+    HASH_FIND(hh,head,findptr,sizeof(void *),out)
+#define HASH_ADD_PTR(head,ptrfield,add)                                          \
+    HASH_ADD(hh,head,ptrfield,sizeof(void *),add)
+#define HASH_DEL(head,delptr)                                                    \
+    HASH_DELETE(hh,head,delptr)
+
+/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.
+ * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
+ */
+#ifdef HASH_DEBUG
+#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
+#define HASH_FSCK(hh,head)                                                       \
+do {                                                                             \
+    unsigned _bkt_i;                                                             \
+    unsigned _count, _bkt_count;                                                 \
+    char *_prev;                                                                 \
+    struct UT_hash_handle *_thh;                                                 \
+    if (head) {                                                                  \
+        _count = 0;                                                              \
+        for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) {       \
+            _bkt_count = 0;                                                      \
+            _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head;                      \
+            _prev = NULL;                                                        \
+            while (_thh) {                                                       \
+               if (_prev != (char*)(_thh->hh_prev)) {                            \
+                   HASH_OOPS("invalid hh_prev %p, actual %p\n",                  \
+                    _thh->hh_prev, _prev );                                      \
+               }                                                                 \
+               _bkt_count++;                                                     \
+               _prev = (char*)(_thh);                                            \
+               _thh = _thh->hh_next;                                             \
+            }                                                                    \
+            _count += _bkt_count;                                                \
+            if ((head)->hh.tbl->buckets[_bkt_i].count !=  _bkt_count) {          \
+               HASH_OOPS("invalid bucket count %d, actual %d\n",                 \
+                (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count);              \
+            }                                                                    \
+        }                                                                        \
+        if (_count != (head)->hh.tbl->num_items) {                               \
+            HASH_OOPS("invalid hh item count %d, actual %d\n",                   \
+                (head)->hh.tbl->num_items, _count );                             \
+        }                                                                        \
+        /* traverse hh in app order; check next/prev integrity, count */         \
+        _count = 0;                                                              \
+        _prev = NULL;                                                            \
+        _thh =  &(head)->hh;                                                     \
+        while (_thh) {                                                           \
+           _count++;                                                             \
+           if (_prev !=(char*)(_thh->prev)) {                                    \
+              HASH_OOPS("invalid prev %p, actual %p\n",                          \
+                    _thh->prev, _prev );                                         \
+           }                                                                     \
+           _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh);                    \
+           _thh = ( _thh->next ?  (UT_hash_handle*)((char*)(_thh->next) +        \
+                                  (head)->hh.tbl->hho) : NULL );                 \
+        }                                                                        \
+        if (_count != (head)->hh.tbl->num_items) {                               \
+            HASH_OOPS("invalid app item count %d, actual %d\n",                  \
+                (head)->hh.tbl->num_items, _count );                             \
+        }                                                                        \
+    }                                                                            \
+} while (0)
+#else
+#define HASH_FSCK(hh,head) 
+#endif
+
+/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to 
+ * the descriptor to which this macro is defined for tuning the hash function.
+ * The app can #include <unistd.h> to get the prototype for write(2). */
+#ifdef HASH_EMIT_KEYS
+#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)                                   \
+do {                                                                             \
+    unsigned _klen = fieldlen;                                                   \
+    write(HASH_EMIT_KEYS, &_klen, sizeof(_klen));                                \
+    write(HASH_EMIT_KEYS, keyptr, fieldlen);                                     \
+} while (0)
+#else 
+#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)                    
+#endif
+
+/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
+#ifdef HASH_FUNCTION 
+#define HASH_FCN HASH_FUNCTION
+#else
+#define HASH_FCN HASH_JEN
+#endif
+
+/* The Bernstein hash function, used in Perl prior to v5.6 */
+#define HASH_BER(key,keylen,num_bkts,hashv,bkt)                                  \
+do {                                                                             \
+  unsigned _hb_keylen=keylen;                                                    \
+  char *_hb_key=(char*)(key);                                                    \
+  (hashv) = 0;                                                                   \
+  while (_hb_keylen--)  { (hashv) = ((hashv) * 33) + *_hb_key++; }               \
+  bkt = (hashv) & (num_bkts-1);                                                  \
+} while (0)
+
+
+/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at 
+ * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
+#define HASH_SAX(key,keylen,num_bkts,hashv,bkt)                                  \
+do {                                                                             \
+  unsigned _sx_i;                                                                \
+  char *_hs_key=(char*)(key);                                                    \
+  hashv = 0;                                                                     \
+  for(_sx_i=0; _sx_i < keylen; _sx_i++)                                          \
+      hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i];                     \
+  bkt = hashv & (num_bkts-1);                                                    \
+} while (0)
+
+#define HASH_FNV(key,keylen,num_bkts,hashv,bkt)                                  \
+do {                                                                             \
+  unsigned _fn_i;                                                                \
+  char *_hf_key=(char*)(key);                                                    \
+  hashv = 2166136261UL;                                                          \
+  for(_fn_i=0; _fn_i < keylen; _fn_i++)                                          \
+      hashv = (hashv * 16777619) ^ _hf_key[_fn_i];                               \
+  bkt = hashv & (num_bkts-1);                                                    \
+} while(0) 
+ 
+#define HASH_OAT(key,keylen,num_bkts,hashv,bkt)                                  \
+do {                                                                             \
+  unsigned _ho_i;                                                                \
+  char *_ho_key=(char*)(key);                                                    \
+  hashv = 0;                                                                     \
+  for(_ho_i=0; _ho_i < keylen; _ho_i++) {                                        \
+      hashv += _ho_key[_ho_i];                                                   \
+      hashv += (hashv << 10);                                                    \
+      hashv ^= (hashv >> 6);                                                     \
+  }                                                                              \
+  hashv += (hashv << 3);                                                         \
+  hashv ^= (hashv >> 11);                                                        \
+  hashv += (hashv << 15);                                                        \
+  bkt = hashv & (num_bkts-1);                                                    \
+} while(0)
+
+#define HASH_JEN_MIX(a,b,c)                                                      \
+do {                                                                             \
+  a -= b; a -= c; a ^= ( c >> 13 );                                              \
+  b -= c; b -= a; b ^= ( a << 8 );                                               \
+  c -= a; c -= b; c ^= ( b >> 13 );                                              \
+  a -= b; a -= c; a ^= ( c >> 12 );                                              \
+  b -= c; b -= a; b ^= ( a << 16 );                                              \
+  c -= a; c -= b; c ^= ( b >> 5 );                                               \
+  a -= b; a -= c; a ^= ( c >> 3 );                                               \
+  b -= c; b -= a; b ^= ( a << 10 );                                              \
+  c -= a; c -= b; c ^= ( b >> 15 );                                              \
+} while (0)
+
+#define HASH_JEN(key,keylen,num_bkts,hashv,bkt)                                  \
+do {                                                                             \
+  unsigned _hj_i,_hj_j,_hj_k;                                                    \
+  char *_hj_key=(char*)(key);                                                    \
+  hashv = 0xfeedbeef;                                                            \
+  _hj_i = _hj_j = 0x9e3779b9;                                                    \
+  _hj_k = (unsigned)keylen;                                                                \
+  while (_hj_k >= 12) {                                                          \
+    _hj_i +=    (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 )                      \
+        + ( (unsigned)_hj_key[2] << 16 )                                         \
+        + ( (unsigned)_hj_key[3] << 24 ) );                                      \
+    _hj_j +=    (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 )                      \
+        + ( (unsigned)_hj_key[6] << 16 )                                         \
+        + ( (unsigned)_hj_key[7] << 24 ) );                                      \
+    hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 )                         \
+        + ( (unsigned)_hj_key[10] << 16 )                                        \
+        + ( (unsigned)_hj_key[11] << 24 ) );                                     \
+                                                                                 \
+     HASH_JEN_MIX(_hj_i, _hj_j, hashv);                                          \
+                                                                                 \
+     _hj_key += 12;                                                              \
+     _hj_k -= 12;                                                                \
+  }                                                                              \
+  hashv += keylen;                                                               \
+  switch ( _hj_k ) {                                                             \
+     case 11: hashv += ( (unsigned)_hj_key[10] << 24 );                          \
+     case 10: hashv += ( (unsigned)_hj_key[9] << 16 );                           \
+     case 9:  hashv += ( (unsigned)_hj_key[8] << 8 );                            \
+     case 8:  _hj_j += ( (unsigned)_hj_key[7] << 24 );                           \
+     case 7:  _hj_j += ( (unsigned)_hj_key[6] << 16 );                           \
+     case 6:  _hj_j += ( (unsigned)_hj_key[5] << 8 );                            \
+     case 5:  _hj_j += _hj_key[4];                                               \
+     case 4:  _hj_i += ( (unsigned)_hj_key[3] << 24 );                           \
+     case 3:  _hj_i += ( (unsigned)_hj_key[2] << 16 );                           \
+     case 2:  _hj_i += ( (unsigned)_hj_key[1] << 8 );                            \
+     case 1:  _hj_i += _hj_key[0];                                               \
+  }                                                                              \
+  HASH_JEN_MIX(_hj_i, _hj_j, hashv);                                             \
+  bkt = hashv & (num_bkts-1);                                                    \
+} while(0)
+
+/* The Paul Hsieh hash function */
+#undef get16bits
+#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__)             \
+  || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
+#define get16bits(d) (*((const uint16_t *) (d)))
+#endif
+
+#if !defined (get16bits)
+#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)             \
+                       +(uint32_t)(((const uint8_t *)(d))[0]) )
+#endif
+#define HASH_SFH(key,keylen,num_bkts,hashv,bkt)                                  \
+do {                                                                             \
+  char *_sfh_key=(char*)(key);                                                   \
+  uint32_t _sfh_tmp, _sfh_len = keylen;                                          \
+                                                                                 \
+  int _sfh_rem = _sfh_len & 3;                                                   \
+  _sfh_len >>= 2;                                                                \
+  hashv = 0xcafebabe;                                                            \
+                                                                                 \
+  /* Main loop */                                                                \
+  for (;_sfh_len > 0; _sfh_len--) {                                              \
+    hashv    += get16bits (_sfh_key);                                            \
+    _sfh_tmp       = (get16bits (_sfh_key+2) << 11) ^ hashv;                     \
+    hashv     = (hashv << 16) ^ _sfh_tmp;                                        \
+    _sfh_key += 2*sizeof (uint16_t);                                             \
+    hashv    += hashv >> 11;                                                     \
+  }                                                                              \
+                                                                                 \
+  /* Handle end cases */                                                         \
+  switch (_sfh_rem) {                                                            \
+    case 3: hashv += get16bits (_sfh_key);                                       \
+            hashv ^= hashv << 16;                                                \
+            hashv ^= _sfh_key[sizeof (uint16_t)] << 18;                          \
+            hashv += hashv >> 11;                                                \
+            break;                                                               \
+    case 2: hashv += get16bits (_sfh_key);                                       \
+            hashv ^= hashv << 11;                                                \
+            hashv += hashv >> 17;                                                \
+            break;                                                               \
+    case 1: hashv += *_sfh_key;                                                  \
+            hashv ^= hashv << 10;                                                \
+            hashv += hashv >> 1;                                                 \
+  }                                                                              \
+                                                                                 \
+    /* Force "avalanching" of final 127 bits */                                  \
+    hashv ^= hashv << 3;                                                         \
+    hashv += hashv >> 5;                                                         \
+    hashv ^= hashv << 4;                                                         \
+    hashv += hashv >> 17;                                                        \
+    hashv ^= hashv << 25;                                                        \
+    hashv += hashv >> 6;                                                         \
+    bkt = hashv & (num_bkts-1);                                                  \
+} while(0) 
+
+#ifdef HASH_USING_NO_STRICT_ALIASING
+/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads.
+ * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
+ * MurmurHash uses the faster approach only on CPU's where we know it's safe. 
+ *
+ * Note the preprocessor built-in defines can be emitted using:
+ *
+ *   gcc -m64 -dM -E - < /dev/null                  (on gcc)
+ *   cc -## a.c (where a.c is a simple test file)   (Sun Studio)
+ */
+#if (defined(__i386__) || defined(__x86_64__)  || defined(_M_IX86))
+#define MUR_GETBLOCK(p,i) p[i]
+#else /* non intel */
+#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 0x3) == 0)
+#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 0x3) == 1)
+#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 0x3) == 2)
+#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 0x3) == 3)
+#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL))
+#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__))
+#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24))
+#define MUR_TWO_TWO(p)   ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16))
+#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >>  8))
+#else /* assume little endian non-intel */
+#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24))
+#define MUR_TWO_TWO(p)   ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16))
+#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) <<  8))
+#endif
+#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) :           \
+                            (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \
+                             (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) :  \
+                                                      MUR_ONE_THREE(p))))
+#endif
+#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))
+#define MUR_FMIX(_h) \
+do {                 \
+  _h ^= _h >> 16;    \
+  _h *= 0x85ebca6b;  \
+  _h ^= _h >> 13;    \
+  _h *= 0xc2b2ae35l; \
+  _h ^= _h >> 16;    \
+} while(0)
+
+#define HASH_MUR(key,keylen,num_bkts,hashv,bkt)                        \
+do {                                                                   \
+  const uint8_t *_mur_data = (const uint8_t*)(key);                    \
+  const int _mur_nblocks = (keylen) / 4;                               \
+  uint32_t _mur_h1 = 0xf88D5353;                                       \
+  uint32_t _mur_c1 = 0xcc9e2d51;                                       \
+  uint32_t _mur_c2 = 0x1b873593;                                       \
+  uint32_t _mur_k1 = 0;                                                \
+  const uint8_t *_mur_tail;                                            \
+  const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+_mur_nblocks*4); \
+  int _mur_i;                                                          \
+  for(_mur_i = -_mur_nblocks; _mur_i; _mur_i++) {                      \
+    _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i);                        \
+    _mur_k1 *= _mur_c1;                                                \
+    _mur_k1 = MUR_ROTL32(_mur_k1,15);                                  \
+    _mur_k1 *= _mur_c2;                                                \
+                                                                       \
+    _mur_h1 ^= _mur_k1;                                                \
+    _mur_h1 = MUR_ROTL32(_mur_h1,13);                                  \
+    _mur_h1 = _mur_h1*5+0xe6546b64;                                    \
+  }                                                                    \
+  _mur_tail = (const uint8_t*)(_mur_data + _mur_nblocks*4);            \
+  _mur_k1=0;                                                           \
+  switch((keylen) & 3) {                                               \
+    case 3: _mur_k1 ^= _mur_tail[2] << 16;                             \
+    case 2: _mur_k1 ^= _mur_tail[1] << 8;                              \
+    case 1: _mur_k1 ^= _mur_tail[0];                                   \
+    _mur_k1 *= _mur_c1;                                                \
+    _mur_k1 = MUR_ROTL32(_mur_k1,15);                                  \
+    _mur_k1 *= _mur_c2;                                                \
+    _mur_h1 ^= _mur_k1;                                                \
+  }                                                                    \
+  _mur_h1 ^= (keylen);                                                 \
+  MUR_FMIX(_mur_h1);                                                   \
+  hashv = _mur_h1;                                                     \
+  bkt = hashv & (num_bkts-1);                                          \
+} while(0)
+#endif  /* HASH_USING_NO_STRICT_ALIASING */
+
+/* key comparison function; return 0 if keys equal */
+#define HASH_KEYCMP(a,b,len) memcmp(a,b,len) 
+
+/* iterate over items in a known bucket to find desired item */
+#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out)                       \
+do {                                                                             \
+ if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head));          \
+ else out=NULL;                                                                  \
+ while (out) {                                                                   \
+    if ((out)->hh.keylen == keylen_in) {                                           \
+        if ((HASH_KEYCMP((out)->hh.key,keyptr,keylen_in)) == 0) break;             \
+    }                                                                            \
+    if ((out)->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,(out)->hh.hh_next)); \
+    else out = NULL;                                                             \
+ }                                                                               \
+} while(0)
+
+/* add an item to a bucket  */
+#define HASH_ADD_TO_BKT(head,addhh)                                              \
+do {                                                                             \
+ head.count++;                                                                   \
+ (addhh)->hh_next = head.hh_head;                                                \
+ (addhh)->hh_prev = NULL;                                                        \
+ if (head.hh_head) { (head).hh_head->hh_prev = (addhh); }                        \
+ (head).hh_head=addhh;                                                           \
+ if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH)             \
+     && (addhh)->tbl->noexpand != 1) {                                           \
+       HASH_EXPAND_BUCKETS((addhh)->tbl);                                        \
+ }                                                                               \
+} while(0)
+
+/* remove an item from a given bucket */
+#define HASH_DEL_IN_BKT(hh,head,hh_del)                                          \
+    (head).count--;                                                              \
+    if ((head).hh_head == hh_del) {                                              \
+      (head).hh_head = hh_del->hh_next;                                          \
+    }                                                                            \
+    if (hh_del->hh_prev) {                                                       \
+        hh_del->hh_prev->hh_next = hh_del->hh_next;                              \
+    }                                                                            \
+    if (hh_del->hh_next) {                                                       \
+        hh_del->hh_next->hh_prev = hh_del->hh_prev;                              \
+    }                                                                
+
+/* Bucket expansion has the effect of doubling the number of buckets
+ * and redistributing the items into the new buckets. Ideally the
+ * items will distribute more or less evenly into the new buckets
+ * (the extent to which this is true is a measure of the quality of
+ * the hash function as it applies to the key domain). 
+ * 
+ * With the items distributed into more buckets, the chain length
+ * (item count) in each bucket is reduced. Thus by expanding buckets
+ * the hash keeps a bound on the chain length. This bounded chain 
+ * length is the essence of how a hash provides constant time lookup.
+ * 
+ * The calculation of tbl->ideal_chain_maxlen below deserves some
+ * explanation. First, keep in mind that we're calculating the ideal
+ * maximum chain length based on the *new* (doubled) bucket count.
+ * In fractions this is just n/b (n=number of items,b=new num buckets).
+ * Since the ideal chain length is an integer, we want to calculate 
+ * ceil(n/b). We don't depend on floating point arithmetic in this
+ * hash, so to calculate ceil(n/b) with integers we could write
+ * 
+ *      ceil(n/b) = (n/b) + ((n%b)?1:0)
+ * 
+ * and in fact a previous version of this hash did just that.
+ * But now we have improved things a bit by recognizing that b is
+ * always a power of two. We keep its base 2 log handy (call it lb),
+ * so now we can write this with a bit shift and logical AND:
+ * 
+ *      ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
+ * 
+ */
+#define HASH_EXPAND_BUCKETS(tbl)                                                 \
+do {                                                                             \
+    unsigned _he_bkt;                                                            \
+    unsigned _he_bkt_i;                                                          \
+    struct UT_hash_handle *_he_thh, *_he_hh_nxt;                                 \
+    UT_hash_bucket *_he_new_buckets, *_he_newbkt;                                \
+    _he_new_buckets = (UT_hash_bucket*)uthash_malloc(                            \
+             2 * tbl->num_buckets * sizeof(struct UT_hash_bucket));              \
+    if (!_he_new_buckets) { uthash_fatal( "out of memory"); }                    \
+    memset(_he_new_buckets, 0,                                                   \
+            2 * tbl->num_buckets * sizeof(struct UT_hash_bucket));               \
+    tbl->ideal_chain_maxlen =                                                    \
+       (tbl->num_items >> (tbl->log2_num_buckets+1)) +                           \
+       ((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0);                    \
+    tbl->nonideal_items = 0;                                                     \
+    for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++)                \
+    {                                                                            \
+        _he_thh = tbl->buckets[ _he_bkt_i ].hh_head;                             \
+        while (_he_thh) {                                                        \
+           _he_hh_nxt = _he_thh->hh_next;                                        \
+           HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt);            \
+           _he_newbkt = &(_he_new_buckets[ _he_bkt ]);                           \
+           if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) {                \
+             tbl->nonideal_items++;                                              \
+             _he_newbkt->expand_mult = _he_newbkt->count /                       \
+                                        tbl->ideal_chain_maxlen;                 \
+           }                                                                     \
+           _he_thh->hh_prev = NULL;                                              \
+           _he_thh->hh_next = _he_newbkt->hh_head;                               \
+           if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev =               \
+                _he_thh;                                                         \
+           _he_newbkt->hh_head = _he_thh;                                        \
+           _he_thh = _he_hh_nxt;                                                 \
+        }                                                                        \
+    }                                                                            \
+    uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
+    tbl->num_buckets *= 2;                                                       \
+    tbl->log2_num_buckets++;                                                     \
+    tbl->buckets = _he_new_buckets;                                              \
+    tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ?         \
+        (tbl->ineff_expands+1) : 0;                                              \
+    if (tbl->ineff_expands > 1) {                                                \
+        tbl->noexpand=1;                                                         \
+        uthash_noexpand_fyi(tbl);                                                \
+    }                                                                            \
+    uthash_expand_fyi(tbl);                                                      \
+} while(0)
+
+
+/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
+/* Note that HASH_SORT assumes the hash handle name to be hh. 
+ * HASH_SRT was added to allow the hash handle name to be passed in. */
+#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
+#define HASH_SRT(hh,head,cmpfcn)                                                 \
+do {                                                                             \
+  unsigned _hs_i;                                                                \
+  unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize;               \
+  struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail;            \
+  if (head) {                                                                    \
+      _hs_insize = 1;                                                            \
+      _hs_looping = 1;                                                           \
+      _hs_list = &((head)->hh);                                                  \
+      while (_hs_looping) {                                                      \
+          _hs_p = _hs_list;                                                      \
+          _hs_list = NULL;                                                       \
+          _hs_tail = NULL;                                                       \
+          _hs_nmerges = 0;                                                       \
+          while (_hs_p) {                                                        \
+              _hs_nmerges++;                                                     \
+              _hs_q = _hs_p;                                                     \
+              _hs_psize = 0;                                                     \
+              for ( _hs_i = 0; _hs_i  < _hs_insize; _hs_i++ ) {                  \
+                  _hs_psize++;                                                   \
+                  _hs_q = (UT_hash_handle*)((_hs_q->next) ?                      \
+                          ((void*)((char*)(_hs_q->next) +                        \
+                          (head)->hh.tbl->hho)) : NULL);                         \
+                  if (! (_hs_q) ) break;                                         \
+              }                                                                  \
+              _hs_qsize = _hs_insize;                                            \
+              while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) {           \
+                  if (_hs_psize == 0) {                                          \
+                      _hs_e = _hs_q;                                             \
+                      _hs_q = (UT_hash_handle*)((_hs_q->next) ?                  \
+                              ((void*)((char*)(_hs_q->next) +                    \
+                              (head)->hh.tbl->hho)) : NULL);                     \
+                      _hs_qsize--;                                               \
+                  } else if ( (_hs_qsize == 0) || !(_hs_q) ) {                   \
+                      _hs_e = _hs_p;                                             \
+                      _hs_p = (UT_hash_handle*)((_hs_p->next) ?                  \
+                              ((void*)((char*)(_hs_p->next) +                    \
+                              (head)->hh.tbl->hho)) : NULL);                     \
+                      _hs_psize--;                                               \
+                  } else if ((                                                   \
+                      cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \
+                             DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \
+                             ) <= 0) {                                           \
+                      _hs_e = _hs_p;                                             \
+                      _hs_p = (UT_hash_handle*)((_hs_p->next) ?                  \
+                              ((void*)((char*)(_hs_p->next) +                    \
+                              (head)->hh.tbl->hho)) : NULL);                     \
+                      _hs_psize--;                                               \
+                  } else {                                                       \
+                      _hs_e = _hs_q;                                             \
+                      _hs_q = (UT_hash_handle*)((_hs_q->next) ?                  \
+                              ((void*)((char*)(_hs_q->next) +                    \
+                              (head)->hh.tbl->hho)) : NULL);                     \
+                      _hs_qsize--;                                               \
+                  }                                                              \
+                  if ( _hs_tail ) {                                              \
+                      _hs_tail->next = ((_hs_e) ?                                \
+                            ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL);          \
+                  } else {                                                       \
+                      _hs_list = _hs_e;                                          \
+                  }                                                              \
+                  _hs_e->prev = ((_hs_tail) ?                                    \
+                     ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL);              \
+                  _hs_tail = _hs_e;                                              \
+              }                                                                  \
+              _hs_p = _hs_q;                                                     \
+          }                                                                      \
+          _hs_tail->next = NULL;                                                 \
+          if ( _hs_nmerges <= 1 ) {                                              \
+              _hs_looping=0;                                                     \
+              (head)->hh.tbl->tail = _hs_tail;                                   \
+              DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list));      \
+          }                                                                      \
+          _hs_insize *= 2;                                                       \
+      }                                                                          \
+      HASH_FSCK(hh,head);                                                        \
+ }                                                                               \
+} while (0)
+
+/* This function selects items from one hash into another hash. 
+ * The end result is that the selected items have dual presence 
+ * in both hashes. There is no copy of the items made; rather 
+ * they are added into the new hash through a secondary hash 
+ * hash handle that must be present in the structure. */
+#define HASH_SELECT(hh_dst, dst, hh_src, src, cond)                              \
+do {                                                                             \
+  unsigned _src_bkt, _dst_bkt;                                                   \
+  void *_last_elt=NULL, *_elt;                                                   \
+  UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL;                         \
+  ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst));                 \
+  if (src) {                                                                     \
+    for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) {     \
+      for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head;                \
+          _src_hh;                                                               \
+          _src_hh = _src_hh->hh_next) {                                          \
+          _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh);                       \
+          if (cond(_elt)) {                                                      \
+            _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho);               \
+            _dst_hh->key = _src_hh->key;                                         \
+            _dst_hh->keylen = _src_hh->keylen;                                   \
+            _dst_hh->hashv = _src_hh->hashv;                                     \
+            _dst_hh->prev = _last_elt;                                           \
+            _dst_hh->next = NULL;                                                \
+            if (_last_elt_hh) { _last_elt_hh->next = _elt; }                     \
+            if (!dst) {                                                          \
+              DECLTYPE_ASSIGN(dst,_elt);                                         \
+              HASH_MAKE_TABLE(hh_dst,dst);                                       \
+            } else {                                                             \
+              _dst_hh->tbl = (dst)->hh_dst.tbl;                                  \
+            }                                                                    \
+            HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt);    \
+            HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh);            \
+            (dst)->hh_dst.tbl->num_items++;                                      \
+            _last_elt = _elt;                                                    \
+            _last_elt_hh = _dst_hh;                                              \
+          }                                                                      \
+      }                                                                          \
+    }                                                                            \
+  }                                                                              \
+  HASH_FSCK(hh_dst,dst);                                                         \
+} while (0)
+
+#define HASH_CLEAR(hh,head)                                                      \
+do {                                                                             \
+  if (head) {                                                                    \
+    uthash_free((head)->hh.tbl->buckets,                                         \
+                (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket));      \
+    HASH_BLOOM_FREE((head)->hh.tbl);                                             \
+    uthash_free((head)->hh.tbl, sizeof(UT_hash_table));                          \
+    (head)=NULL;                                                                 \
+  }                                                                              \
+} while(0)
+
+#ifdef NO_DECLTYPE
+#define HASH_ITER(hh,head,el,tmp)                                                \
+for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL);       \
+  el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL)) 
+#else
+#define HASH_ITER(hh,head,el,tmp)                                                \
+for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL);                 \
+  el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL))
+#endif
+
+/* obtain a count of items in the hash */
+#define HASH_COUNT(head) HASH_CNT(hh,head) 
+#define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0)
+
+typedef struct UT_hash_bucket {
+   struct UT_hash_handle *hh_head;
+   unsigned count;
+
+   /* expand_mult is normally set to 0. In this situation, the max chain length
+    * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
+    * the bucket's chain exceeds this length, bucket expansion is triggered). 
+    * However, setting expand_mult to a non-zero value delays bucket expansion
+    * (that would be triggered by additions to this particular bucket)
+    * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
+    * (The multiplier is simply expand_mult+1). The whole idea of this
+    * multiplier is to reduce bucket expansions, since they are expensive, in
+    * situations where we know that a particular bucket tends to be overused.
+    * It is better to let its chain length grow to a longer yet-still-bounded
+    * value, than to do an O(n) bucket expansion too often. 
+    */
+   unsigned expand_mult;
+
+} UT_hash_bucket;
+
+/* random signature used only to find hash tables in external analysis */
+#define HASH_SIGNATURE 0xa0111fe1
+#define HASH_BLOOM_SIGNATURE 0xb12220f2
+
+typedef struct UT_hash_table {
+   UT_hash_bucket *buckets;
+   unsigned num_buckets, log2_num_buckets;
+   unsigned num_items;
+   struct UT_hash_handle *tail; /* tail hh in app order, for fast append    */
+   ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */
+
+   /* in an ideal situation (all buckets used equally), no bucket would have
+    * more than ceil(#items/#buckets) items. that's the ideal chain length. */
+   unsigned ideal_chain_maxlen;
+
+   /* nonideal_items is the number of items in the hash whose chain position
+    * exceeds the ideal chain maxlen. these items pay the penalty for an uneven
+    * hash distribution; reaching them in a chain traversal takes >ideal steps */
+   unsigned nonideal_items;
+
+   /* ineffective expands occur when a bucket doubling was performed, but 
+    * afterward, more than half the items in the hash had nonideal chain
+    * positions. If this happens on two consecutive expansions we inhibit any
+    * further expansion, as it's not helping; this happens when the hash
+    * function isn't a good fit for the key domain. When expansion is inhibited
+    * the hash will still work, albeit no longer in constant time. */
+   unsigned ineff_expands, noexpand;
+
+   uint32_t signature; /* used only to find hash tables in external analysis */
+#ifdef HASH_BLOOM
+   uint32_t bloom_sig; /* used only to test bloom exists in external analysis */
+   uint8_t *bloom_bv;
+   char bloom_nbits;
+#endif
+
+} UT_hash_table;
+
+typedef struct UT_hash_handle {
+   struct UT_hash_table *tbl;
+   void *prev;                       /* prev element in app order      */
+   void *next;                       /* next element in app order      */
+   struct UT_hash_handle *hh_prev;   /* previous hh in bucket order    */
+   struct UT_hash_handle *hh_next;   /* next hh in bucket order        */
+   void *key;                        /* ptr to enclosing struct's key  */
+   unsigned keylen;                  /* enclosing struct's key len     */
+   unsigned hashv;                   /* result of hash-fcn(key)        */
+} UT_hash_handle;
+
+#endif /* UTHASH_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/cxxfilt/Makefile	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,15 @@
+# $Id: Makefile 2066 2011-10-26 15:40:28Z jkoshy $
+
+TOP=	..
+
+PROG=	c++filt
+SRCS=	cxxfilt.c
+
+WARNS?=	6
+
+DPADD=	${LIBELFTC} ${LIBELF}
+LDADD=	-lelftc -lelf
+
+MAN1=	c++filt.1
+
+.include "${TOP}/mk/elftoolchain.prog.mk"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/cxxfilt/c++filt.1	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,109 @@
+.\" Copyright (c) 2009-2011 Joseph Koshy <jkoshy@users.sourceforge.net>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer
+.\"    in this position and unchanged.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $Id: c++filt.1 3195 2015-05-12 17:22:19Z emaste $
+.\"
+.Dd August 24, 2011
+.Os
+.Dt C++FILT 1
+.Sh NAME
+.Nm c++filt
+.Nd decode C++ symbols
+.Sh SYNOPSIS
+.Nm
+.Op Fl -help
+.Op Fl _ | Fl -strip-underscores
+.Op Fl n | Fl -no-strip-underscores
+.Op Fl p | Fl -no-params
+.Op Fl s Ar scheme | Fl -format Ns = Ns Ar scheme
+.Op Fl V | Fl -version
+.Op Ar encoded-names ...
+.Sh DESCRIPTION
+The
+.Nm
+utility translates encoded C++ symbol names to human-readable form.
+.Pp
+The
+.Nm
+utility has two operating modes.
+.Bl -bullet
+.It
+If arguments
+.Ar encoded-names
+are not specified, then
+.Nm
+will act as a filter, reading from standard input
+and writing to standard output.
+.It
+If arguments
+.Ar encoded-names
+are specified, then
+.Nm
+will decode each such argument in turn, writing its decoded form
+to standard output.
+.El
+.Pp
+The
+.Nm
+utility recognizes the following options:
+.Bl -tag -width indent
+.It Fl -help
+Print a help message and exit.
+.It Fl _ | Fl -strip-underscores
+Remove a leading underscore from symbol names prior to decoding them.
+.It Fl n | Fl -no-strip-underscores
+Do not remove leading underscores from names.
+.It Fl p | Fl -no-params
+This option is recognized but ignored.
+.It Fl s Ar scheme | Fl -format Ns = Ns Ar scheme
+Select the encoding scheme to use.
+Argument
+.Ar scheme
+can be one of the following:
+.Bl -tag -width "gnu-v5"
+.It Ar arm
+Use the encoding scheme specified by the C++ Annotated Reference Manual.
+.It Ar auto
+Guess the encoding scheme from the input.
+.It Ar gnu
+Use the encoding scheme used by the GNU C++ compiler.
+.It Ar gnu-v3
+Use the encoding scheme used by the GNU C++ compiler, version 3.
+.El
+.It Fl V | Fl -version
+Print a version identifier for
+.Nm
+and exit.
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh SEE ALSO
+.Xr nm 1 ,
+.Xr strip 1 ,
+.Xr elftc_demangle 3
+.Sh AUTHORS
+The
+.Nm
+utility was written by
+.An Kai Wang Aq Mt kaiwang27@users.sourceforge.net .
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/cxxfilt/cxxfilt.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,203 @@
+/*-
+ * Copyright (c) 2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <ctype.h>
+#include <err.h>
+#include <getopt.h>
+#include <libelftc.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "_elftc.h"
+
+ELFTC_VCSID("$Id: cxxfilt.c 3499 2016-11-25 16:06:29Z emaste $");
+
+#define	STRBUFSZ	8192
+
+static int stripus = 0;
+static int noparam = 0;
+static int format = 0;
+
+enum options
+{
+	OPTION_HELP,
+	OPTION_VERSION
+};
+
+static struct option longopts[] =
+{
+	{"format", required_argument, NULL, 's'},
+	{"help", no_argument, NULL, OPTION_HELP},
+	{"no-params", no_argument, NULL, 'p'},
+	{"no-strip-underscores", no_argument, NULL, 'n'},
+	{"strip-underscores", no_argument, NULL, '_'},
+	{"version", no_argument, NULL, 'V'},
+	{NULL, 0, NULL, 0}
+};
+
+static struct {
+	const char *fname;
+	int fvalue;
+} flist[] = {
+	{"auto", 0},
+	{"arm", ELFTC_DEM_ARM},
+	{"gnu", ELFTC_DEM_GNU2},
+	{"gnu-v3", ELFTC_DEM_GNU3}
+};
+
+#define	USAGE_MESSAGE	"\
+Usage: %s [options] [encoded-names...]\n\
+  Translate C++ symbol names to human-readable form.\n\n\
+  Options:\n\
+  -_ | --strip-underscores     Remove leading underscores prior to decoding.\n\
+  -n | --no-strip-underscores  Do not remove leading underscores.\n\
+  -p | --no-params             (Accepted but ignored).\n\
+  -s SCHEME | --format=SCHEME  Select the encoding scheme to use.\n\
+                               Valid schemes are: 'arm', 'auto', 'gnu' and\n\
+                               'gnu-v3'.\n\
+  --help                       Print a help message.\n\
+  --version                    Print a version identifier and exit.\n"
+
+static void
+usage(void)
+{
+
+	(void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
+	exit(1);
+}
+
+static void
+version(void)
+{
+	fprintf(stderr, "%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version());
+	exit(0);
+}
+
+static int
+find_format(const char *fstr)
+{
+	int i;
+
+	for (i = 0; (size_t) i < sizeof(flist) / sizeof(flist[0]); i++) {
+		if (!strcmp(fstr, flist[i].fname))
+		    return (flist[i].fvalue);
+	}
+
+	return (-1);
+}
+
+static char *
+demangle(char *name)
+{
+	static char dem[STRBUFSZ];
+
+	if (stripus && *name == '_')
+		name++;
+
+	if (strlen(name) == 0)
+		return (NULL);
+
+	if (elftc_demangle(name, dem, sizeof(dem), (unsigned) format) < 0)
+		return (NULL);
+
+	return (dem);
+}
+
+int
+main(int argc, char **argv)
+{
+	char *dem, buf[STRBUFSZ];
+	size_t p;
+	int c, n, opt;
+
+	while ((opt = getopt_long(argc, argv, "_nps:V", longopts, NULL)) !=
+	    -1) {
+		switch (opt) {
+		case '_':
+			stripus = 1;
+			break;
+		case 'n':
+			stripus = 0;
+			break;
+		case 'p':
+			noparam = 1;
+			break;
+		case 's':
+			if ((format = find_format(optarg)) < 0)
+				errx(EXIT_FAILURE, "unsupported format: %s",
+				    optarg);
+			break;
+		case 'V':
+			version();
+			/* NOT REACHED */
+		case OPTION_HELP:
+		default:
+			usage();
+			/* NOT REACHED */
+		}
+	}
+
+	argv += optind;
+	argc -= optind;
+
+	if (*argv != NULL) {
+		for (n = 0; n < argc; n++) {
+			if ((dem = demangle(argv[n])) == NULL)
+				printf("%s\n", argv[n]);
+			else
+				printf("%s\n", dem);
+		}
+	} else {
+		p = 0;
+		for (;;) {
+			setvbuf(stdout, NULL, _IOLBF, 0);
+			c = fgetc(stdin);
+			if (c == EOF || !(isalnum(c) || strchr(".$_", c))) {
+				if (p > 0) {
+					buf[p] = '\0';
+					if ((dem = demangle(buf)) == NULL)
+						printf("%s", buf);
+					else
+						printf("%s", dem);
+					p = 0;
+				}
+				if (c == EOF)
+					break;
+				putchar(c);
+			} else {
+				if ((size_t) p >= sizeof(buf) - 1)
+					warnx("buffer overflowed");
+				else
+					buf[p++] = (char) c;
+			}
+
+		}
+	}
+
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/elfcopy/Makefile	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,56 @@
+# $Id: Makefile 3608 2018-04-14 21:23:04Z jkoshy $
+
+TOP=	..
+
+.include "${TOP}/mk/elftoolchain.components.mk"
+
+PROG=	elfcopy
+
+SRCS=	archive.c ascii.c binary.c main.c sections.c segments.c \
+	symbols.c
+
+WARNS?=	5
+
+DPADD=	${LIBELF} ${LIBELFTC}
+LDADD=	-lelf -lelftc
+
+.if !defined(LIBELF_AR)
+LDADD+= -larchive
+.endif
+
+.if defined(WITH_PE) && ${WITH_PE} == "yes"
+SRCS+=	pe.c
+CFLAGS+= -DWITH_PE=1
+
+DPADD+=	${LIBPE}
+LDADD+=	-lpe
+.endif
+
+MAN=	elfcopy.1 mcs.1 strip.1
+MLINKS=	elfcopy.1 objcopy.1
+
+NO_SHARED?=	yes
+
+LINKS=	${BINDIR}/elfcopy ${BINDIR}/mcs		\
+	${BINDIR}/elfcopy ${BINDIR}/objcopy 	\
+	${BINDIR}/elfcopy ${BINDIR}/strip
+
+EXTRA_TARGETS=	mcs strip objcopy
+
+CLEANFILES+=	${EXTRA_TARGETS}
+
+# Create in-place symbolic links to "elfcopy" at build time.
+
+all:	${EXTRA_TARGETS}
+
+${EXTRA_TARGETS}:	${PROG}
+	ln -s ${PROG} ${.TARGET}
+
+.include "${TOP}/mk/elftoolchain.prog.mk"
+
+.if ${OS_HOST} == "OpenBSD"
+CFLAGS+=	-I/usr/local/include
+LDFLAGS+=	-L/usr/local/lib
+.elif ${OS_HOST} == "DragonFly"
+LDADD+=		-lbz2
+.endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/elfcopy/archive.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,526 @@
+/*-
+ * Copyright (c) 2007-2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <err.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef LIBELF_AR
+#include <archive.h>
+#include <archive_entry.h>
+#endif	/* ! LIBELF_AR */
+
+#include "elfcopy.h"
+
+ELFTC_VCSID("$Id: archive.c 3490 2016-08-31 00:12:22Z emaste $");
+
+#define _ARMAG_LEN 8		/* length of ar magic string */
+#define _ARHDR_LEN 60		/* length of ar header */
+#define _INIT_AS_CAP 128	/* initial archive string table size */
+#define _INIT_SYMOFF_CAP (256*(sizeof(uint32_t))) /* initial so table size */
+#define _INIT_SYMNAME_CAP 1024			  /* initial sn table size */
+#define _MAXNAMELEN_SVR4 15	/* max member name length in svr4 variant */
+
+#ifndef LIBELF_AR
+static void ac_read_objs(struct elfcopy *ecp, int ifd);
+static void ac_write_cleanup(struct elfcopy *ecp);
+static void ac_write_data(struct archive *a, const void *buf, size_t s);
+static void ac_write_objs(struct elfcopy *ecp, int ofd);
+#endif	/* ! LIBELF_AR */
+static void add_to_ar_str_table(struct elfcopy *elfcopy, const char *name);
+static void add_to_ar_sym_table(struct elfcopy *ecp, const char *name);
+static void extract_arsym(struct elfcopy *ecp);
+static void process_ar_obj(struct elfcopy *ecp, struct ar_obj *obj);
+static void sync_ar(struct elfcopy *ecp);
+
+
+static void
+process_ar_obj(struct elfcopy *ecp, struct ar_obj *obj)
+{
+	struct stat	 sb;
+	char		*tempfile;
+	int		 fd;
+
+	/* Output to a temporary file. */
+	create_tempfile(&tempfile, &fd);
+	if ((ecp->eout = elf_begin(fd, ELF_C_WRITE, NULL)) == NULL)
+		errx(EXIT_FAILURE, "elf_begin() failed: %s",
+		    elf_errmsg(-1));
+	elf_flagelf(ecp->eout, ELF_C_SET, ELF_F_LAYOUT);
+	create_elf(ecp);
+	elf_end(ecp->ein);
+	elf_end(ecp->eout);
+	free(obj->buf);
+	obj->buf = NULL;
+
+	/* Extract archive symbols. */
+	if (lseek(fd, 0, SEEK_SET) < 0)
+		err(EXIT_FAILURE, "lseek failed for '%s'", tempfile);
+	if ((ecp->eout = elf_begin(fd, ELF_C_READ, NULL)) == NULL)
+		errx(EXIT_FAILURE, "elf_begin() failed: %s",
+		    elf_errmsg(-1));
+	extract_arsym(ecp);
+	elf_end(ecp->eout);
+
+	if (fstat(fd, &sb) == -1)
+		err(EXIT_FAILURE, "fstat %s failed", tempfile);
+	if (lseek(fd, 0, SEEK_SET) < 0)
+		err(EXIT_FAILURE, "lseek %s failed", tempfile);
+	obj->size = sb.st_size;
+	if ((obj->maddr = malloc(obj->size)) == NULL)
+		err(EXIT_FAILURE, "memory allocation failed for '%s'",
+		    tempfile);
+	if ((size_t) read(fd, obj->maddr, obj->size) != obj->size)
+		err(EXIT_FAILURE, "read failed for '%s'", tempfile);
+	if (unlink(tempfile))
+		err(EXIT_FAILURE, "unlink %s failed", tempfile);
+	free(tempfile);
+	close(fd);
+	if (strlen(obj->name) > _MAXNAMELEN_SVR4)
+		add_to_ar_str_table(ecp, obj->name);
+	ecp->rela_off += _ARHDR_LEN + obj->size + obj->size % 2;
+	STAILQ_INSERT_TAIL(&ecp->v_arobj, obj, objs);
+}
+
+/*
+ * Append to the archive string table buffer.
+ */
+static void
+add_to_ar_str_table(struct elfcopy *ecp, const char *name)
+{
+
+	if (ecp->as == NULL) {
+		ecp->as_cap = _INIT_AS_CAP;
+		ecp->as_sz = 0;
+		if ((ecp->as = malloc(ecp->as_cap)) == NULL)
+			err(EXIT_FAILURE, "malloc failed");
+	}
+
+	/*
+	 * The space required for holding one member name in as table includes:
+	 * strlen(name) + (1 for '/') + (1 for '\n') + (possibly 1 for padding).
+	 */
+	while (ecp->as_sz + strlen(name) + 3 > ecp->as_cap) {
+		ecp->as_cap *= 2;
+		ecp->as = realloc(ecp->as, ecp->as_cap);
+		if (ecp->as == NULL)
+			err(EXIT_FAILURE, "realloc failed");
+	}
+	strncpy(&ecp->as[ecp->as_sz], name, strlen(name));
+	ecp->as_sz += strlen(name);
+	ecp->as[ecp->as_sz++] = '/';
+	ecp->as[ecp->as_sz++] = '\n';
+}
+
+/*
+ * Append to the archive symbol table buffer.
+ */
+static void
+add_to_ar_sym_table(struct elfcopy *ecp, const char *name)
+{
+
+	if (ecp->s_so == NULL) {
+		if ((ecp->s_so = malloc(_INIT_SYMOFF_CAP)) == NULL)
+			err(EXIT_FAILURE, "malloc failed");
+		ecp->s_so_cap = _INIT_SYMOFF_CAP;
+		ecp->s_cnt = 0;
+	}
+
+	if (ecp->s_sn == NULL) {
+		if ((ecp->s_sn = malloc(_INIT_SYMNAME_CAP)) == NULL)
+			err(EXIT_FAILURE, "malloc failed");
+		ecp->s_sn_cap = _INIT_SYMNAME_CAP;
+		ecp->s_sn_sz = 0;
+	}
+
+	if (ecp->s_cnt * sizeof(uint32_t) >= ecp->s_so_cap) {
+		ecp->s_so_cap *= 2;
+		ecp->s_so = realloc(ecp->s_so, ecp->s_so_cap);
+		if (ecp->s_so == NULL)
+			err(EXIT_FAILURE, "realloc failed");
+	}
+	ecp->s_so[ecp->s_cnt] = ecp->rela_off;
+	ecp->s_cnt++;
+
+	/*
+	 * The space required for holding one symbol name in sn table includes:
+	 * strlen(name) + (1 for '\n') + (possibly 1 for padding).
+	 */
+	while (ecp->s_sn_sz + strlen(name) + 2 > ecp->s_sn_cap) {
+		ecp->s_sn_cap *= 2;
+		ecp->s_sn = realloc(ecp->s_sn, ecp->s_sn_cap);
+		if (ecp->s_sn == NULL)
+			err(EXIT_FAILURE, "realloc failed");
+	}
+	strncpy(&ecp->s_sn[ecp->s_sn_sz], name, strlen(name));
+	ecp->s_sn_sz += strlen(name);
+	ecp->s_sn[ecp->s_sn_sz++] = '\0';
+}
+
+static void
+sync_ar(struct elfcopy *ecp)
+{
+	size_t s_sz;		/* size of archive symbol table. */
+	size_t pm_sz;		/* size of pseudo members */
+	int i;
+
+	/*
+	 * Pad the symbol name string table. It is treated specially because
+	 * symbol name table should be padded by a '\0', not the common '\n'
+	 * for other members. The size of sn table includes the pad bit.
+	 */
+	if (ecp->s_cnt != 0 && ecp->s_sn_sz % 2 != 0)
+		ecp->s_sn[ecp->s_sn_sz++] = '\0';
+
+	/*
+	 * Archive string table is padded by a "\n" as the normal members.
+	 * The difference is that the size of archive string table counts
+	 * in the pad bit, while normal members' size fileds do not.
+	 */
+	if (ecp->as != NULL && ecp->as_sz % 2 != 0)
+		ecp->as[ecp->as_sz++] = '\n';
+
+	/*
+	 * If there is a symbol table, calculate the size of pseudo members,
+	 * convert previously stored relative offsets to absolute ones, and
+	 * then make them Big Endian.
+	 *
+	 * absolute_offset = htobe32(relative_offset + size_of_pseudo_members)
+	 */
+
+	if (ecp->s_cnt != 0) {
+		s_sz = (ecp->s_cnt + 1) * sizeof(uint32_t) + ecp->s_sn_sz;
+		pm_sz = _ARMAG_LEN + (_ARHDR_LEN + s_sz);
+		if (ecp->as != NULL)
+			pm_sz += _ARHDR_LEN + ecp->as_sz;
+		for (i = 0; (size_t)i < ecp->s_cnt; i++)
+			*(ecp->s_so + i) = htobe32(*(ecp->s_so + i) +
+			    pm_sz);
+	}
+}
+
+/*
+ * Extract global symbols from archive members.
+ */
+static void
+extract_arsym(struct elfcopy *ecp)
+{
+	Elf_Scn		*scn;
+	GElf_Shdr	 shdr;
+	GElf_Sym	 sym;
+	Elf_Data	*data;
+	char		*name;
+	size_t		 n, shstrndx;
+	int		 elferr, tabndx, len, i;
+
+	if (elf_kind(ecp->eout) != ELF_K_ELF) {
+		warnx("internal: cannot extract symbols from non-elf object");
+		return;
+	}
+	if (elf_getshstrndx(ecp->eout, &shstrndx) == 0) {
+		warnx("elf_getshstrndx failed: %s", elf_errmsg(-1));
+		return;
+	}
+
+	tabndx = -1;
+	scn = NULL;
+	while ((scn = elf_nextscn(ecp->eout, scn)) != NULL) {
+		if (gelf_getshdr(scn, &shdr) != &shdr) {
+			warnx("elf_getshdr failed: %s", elf_errmsg(-1));
+			continue;
+		}
+		if ((name = elf_strptr(ecp->eout, shstrndx, shdr.sh_name)) ==
+		    NULL) {
+			warnx("elf_strptr failed: %s", elf_errmsg(-1));
+			continue;
+		}
+		if (strcmp(name, ".strtab") == 0) {
+			tabndx = elf_ndxscn(scn);
+			break;
+		}
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		warnx("elf_nextscn failed: %s", elf_errmsg(elferr));
+
+	/* Ignore members without symbol table. */
+	if (tabndx == -1)
+		return;
+
+	scn = NULL;
+	while ((scn = elf_nextscn(ecp->eout, scn)) != NULL) {
+		if (gelf_getshdr(scn, &shdr) != &shdr) {
+			warnx("elf_getshdr failed: %s", elf_errmsg(-1));
+			continue;
+		}
+		if (shdr.sh_type != SHT_SYMTAB)
+			continue;
+
+		data = NULL;
+		n = 0;
+		while (n < shdr.sh_size &&
+		    (data = elf_getdata(scn, data)) != NULL) {
+			len = data->d_size / shdr.sh_entsize;
+			for (i = 0; i < len; i++) {
+				if (gelf_getsym(data, i, &sym) != &sym) {
+					warnx("gelf_getsym failed: %s",
+					     elf_errmsg(-1));
+					continue;
+				}
+
+				/* keep only global or weak symbols */
+				if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL &&
+				    GELF_ST_BIND(sym.st_info) != STB_WEAK)
+					continue;
+
+				/* keep only defined symbols */
+				if (sym.st_shndx == SHN_UNDEF)
+					continue;
+
+				if ((name = elf_strptr(ecp->eout, tabndx,
+				    sym.st_name)) == NULL) {
+					warnx("elf_strptr failed: %s",
+					     elf_errmsg(-1));
+					continue;
+				}
+
+				add_to_ar_sym_table(ecp, name);
+			}
+		}
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		warnx("elf_nextscn failed: %s", elf_errmsg(elferr));
+}
+
+#ifndef LIBELF_AR
+
+/*
+ * Convenient wrapper for general libarchive error handling.
+ */
+#define	AC(CALL) do {							\
+	if ((CALL))							\
+		errx(EXIT_FAILURE, "%s", archive_error_string(a));	\
+} while (0)
+
+/* Earlier versions of libarchive had some functions that returned 'void'. */
+#if	ARCHIVE_VERSION_NUMBER >= 2000000
+#define	ACV(CALL) 	AC(CALL)
+#else
+#define	ACV(CALL)	do {						\
+		(CALL);							\
+	} while (0)
+#endif
+
+int
+ac_detect_ar(int ifd)
+{
+	struct archive		*a;
+	struct archive_entry	*entry;
+	int			 r;
+
+	r = -1;
+	if ((a = archive_read_new()) == NULL)
+		return (0);
+	archive_read_support_format_ar(a);
+	if (archive_read_open_fd(a, ifd, 10240) == ARCHIVE_OK)
+		r = archive_read_next_header(a, &entry);
+	archive_read_close(a);
+	archive_read_free(a);
+
+	return (r == ARCHIVE_OK);
+}
+
+void
+ac_create_ar(struct elfcopy *ecp, int ifd, int ofd)
+{
+
+	ac_read_objs(ecp, ifd);
+	sync_ar(ecp);
+	ac_write_objs(ecp, ofd);
+	ac_write_cleanup(ecp);
+}
+
+static void
+ac_read_objs(struct elfcopy *ecp, int ifd)
+{
+	struct archive		*a;
+	struct archive_entry	*entry;
+	struct ar_obj		*obj;
+	const char		*name;
+	char			*buff;
+	size_t			 size;
+	int			 r;
+
+	ecp->rela_off = 0;
+	if (lseek(ifd, 0, SEEK_SET) == -1)
+		err(EXIT_FAILURE, "lseek failed");
+	if ((a = archive_read_new()) == NULL)
+		errx(EXIT_FAILURE, "archive_read_new failed");
+	archive_read_support_format_ar(a);
+	AC(archive_read_open_fd(a, ifd, 10240));
+	for(;;) {
+		r = archive_read_next_header(a, &entry);
+		if (r == ARCHIVE_FATAL)
+			errx(EXIT_FAILURE, "%s", archive_error_string(a));
+		if (r == ARCHIVE_EOF)
+			break;
+		if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY)
+			warnx("%s", archive_error_string(a));
+		if (r == ARCHIVE_RETRY)
+			continue;
+
+		name = archive_entry_pathname(entry);
+
+		/* skip pseudo members. */
+		if (strcmp(name, "/") == 0 || strcmp(name, "//") == 0)
+			continue;
+
+		size = archive_entry_size(entry);
+
+		if (size > 0) {
+			if ((buff = malloc(size)) == NULL)
+				err(EXIT_FAILURE, "malloc failed");
+			if (archive_read_data(a, buff, size) != (ssize_t)size) {
+				warnx("%s", archive_error_string(a));
+				free(buff);
+				continue;
+			}
+			if ((obj = malloc(sizeof(*obj))) == NULL)
+				err(EXIT_FAILURE, "malloc failed");
+			if ((obj->name = strdup(name)) == NULL)
+				err(EXIT_FAILURE, "strdup failed");
+			obj->buf = buff;
+			obj->uid = archive_entry_uid(entry);
+			obj->gid = archive_entry_gid(entry);
+			obj->md = archive_entry_mode(entry);
+			obj->mtime = archive_entry_mtime(entry);
+			if ((ecp->ein = elf_memory(buff, size)) == NULL)
+				errx(EXIT_FAILURE, "elf_memory() failed: %s",
+				    elf_errmsg(-1));
+			if (elf_kind(ecp->ein) != ELF_K_ELF)
+				errx(EXIT_FAILURE,
+				    "file format not recognized");
+			process_ar_obj(ecp, obj);
+		}
+	}
+	AC(archive_read_close(a));
+	ACV(archive_read_free(a));
+}
+
+static void
+ac_write_objs(struct elfcopy *ecp, int ofd)
+{
+	struct archive		*a;
+	struct archive_entry	*entry;
+	struct ar_obj		*obj;
+	time_t			 timestamp;
+	int			 nr;
+
+	if ((a = archive_write_new()) == NULL)
+		errx(EXIT_FAILURE, "archive_write_new failed");
+	archive_write_set_format_ar_svr4(a);
+	AC(archive_write_open_fd(a, ofd));
+
+	/* Write the archive symbol table, even if it's empty. */
+	entry = archive_entry_new();
+	archive_entry_copy_pathname(entry, "/");
+	if (elftc_timestamp(&timestamp) != 0)
+		err(EXIT_FAILURE, "elftc_timestamp");
+	archive_entry_set_mtime(entry, timestamp, 0);
+	archive_entry_set_size(entry, (ecp->s_cnt + 1) * sizeof(uint32_t) +
+	    ecp->s_sn_sz);
+	AC(archive_write_header(a, entry));
+	nr = htobe32(ecp->s_cnt);
+	ac_write_data(a, &nr, sizeof(uint32_t));
+	ac_write_data(a, ecp->s_so, sizeof(uint32_t) * ecp->s_cnt);
+	ac_write_data(a, ecp->s_sn, ecp->s_sn_sz);
+	archive_entry_free(entry);
+
+	/* Write the archive string table, if exist. */
+	if (ecp->as != NULL) {
+		entry = archive_entry_new();
+		archive_entry_copy_pathname(entry, "//");
+		archive_entry_set_size(entry, ecp->as_sz);
+		AC(archive_write_header(a, entry));
+		ac_write_data(a, ecp->as, ecp->as_sz);
+		archive_entry_free(entry);
+	}
+
+	/* Write normal members. */
+	STAILQ_FOREACH(obj, &ecp->v_arobj, objs) {
+		entry = archive_entry_new();
+		archive_entry_copy_pathname(entry, obj->name);
+		archive_entry_set_uid(entry, obj->uid);
+		archive_entry_set_gid(entry, obj->gid);
+		archive_entry_set_mode(entry, obj->md);
+		archive_entry_set_size(entry, obj->size);
+		archive_entry_set_mtime(entry, obj->mtime, 0);
+		archive_entry_set_filetype(entry, AE_IFREG);
+		AC(archive_write_header(a, entry));
+		ac_write_data(a, obj->maddr, obj->size);
+		archive_entry_free(entry);
+	}
+
+	AC(archive_write_close(a));
+	ACV(archive_write_free(a));
+}
+
+static void
+ac_write_cleanup(struct elfcopy *ecp)
+{
+	struct ar_obj		*obj, *obj_temp;
+
+	STAILQ_FOREACH_SAFE(obj, &ecp->v_arobj, objs, obj_temp) {
+		STAILQ_REMOVE(&ecp->v_arobj, obj, ar_obj, objs);
+		if (obj->maddr != NULL)
+			free(obj->maddr);
+		free(obj->name);
+		free(obj);
+	}
+
+	free(ecp->as);
+	free(ecp->s_so);
+	free(ecp->s_sn);
+	ecp->as = NULL;
+	ecp->s_so = NULL;
+	ecp->s_sn = NULL;
+}
+
+/*
+ * Wrapper for archive_write_data().
+ */
+static void
+ac_write_data(struct archive *a, const void *buf, size_t s)
+{
+	if (archive_write_data(a, buf, s) != (ssize_t)s)
+		errx(EXIT_FAILURE, "%s", archive_error_string(a));
+}
+
+#endif	/* ! LIBELF_AR */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/elfcopy/ascii.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,1079 @@
+/*-
+ * Copyright (c) 2010,2011 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <ctype.h>
+#include <err.h>
+#include <gelf.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "elfcopy.h"
+
+ELFTC_VCSID("$Id: ascii.c 3487 2016-08-24 18:12:08Z emaste $");
+
+static void append_data(struct section *s, const void *buf, size_t sz);
+static char hex_digit(uint8_t n);
+static int hex_value(int x);
+static void finalize_data_section(struct section *s);
+static int ishexdigit(int x);
+static int ihex_read(const char *line, char *type, uint64_t *addr,
+    uint64_t *num, uint8_t *data, size_t *sz);
+static void ihex_write(int ofd, int type, uint64_t addr, uint64_t num,
+    const void *buf, size_t sz);
+static void ihex_write_00(int ofd, uint64_t addr, const void *buf, size_t sz);
+static void ihex_write_01(int ofd);
+static void ihex_write_04(int ofd, uint16_t addr);
+static void ihex_write_05(int ofd, uint64_t e_entry);
+static struct section *new_data_section(struct elfcopy *ecp, int sec_index,
+    uint64_t off, uint64_t addr);
+static int read_num(const char *line, int *len, uint64_t *num, size_t sz,
+    int *checksum);
+static int srec_read(const char *line, char *type, uint64_t *addr,
+    uint8_t *data, size_t *sz);
+static void srec_write(int ofd, char type, uint64_t addr, const void *buf,
+    size_t sz);
+static void srec_write_symtab(int ofd, const char *ofn, Elf *e, Elf_Scn *scn,
+    GElf_Shdr *sh);
+static void srec_write_S0(int ofd, const char *ofn);
+static void srec_write_Sd(int ofd, char dr, uint64_t addr, const void *buf,
+    size_t sz, size_t rlen);
+static void srec_write_Se(int ofd, uint64_t e_entry, int forceS3);
+static void write_num(char *line, int *len, uint64_t num, size_t sz,
+    int *checksum);
+
+#define	_LINE_BUFSZ	1024
+#define	_DATA_BUFSZ	256
+
+/*
+ * Convert ELF object to S-Record.
+ */
+void
+create_srec(struct elfcopy *ecp, int ifd, int ofd, const char *ofn)
+{
+	Elf *e;
+	Elf_Scn *scn;
+	Elf_Data *d;
+	GElf_Ehdr eh;
+	GElf_Shdr sh;
+	uint64_t max_addr;
+	size_t rlen;
+	int elferr, addr_sz;
+	char dr;
+
+	if ((e = elf_begin(ifd, ELF_C_READ, NULL)) == NULL)
+		errx(EXIT_FAILURE, "elf_begin() failed: %s",
+		    elf_errmsg(-1));
+
+	/* Output a symbol table for `symbolsrec' target. */
+	if (!strncmp(ecp->otgt, "symbolsrec", strlen("symbolsrec"))) {
+		scn = NULL;
+		while ((scn = elf_nextscn(e, scn)) != NULL) {
+			if (gelf_getshdr(scn, &sh) == NULL) {
+				warnx("gelf_getshdr failed: %s",
+				    elf_errmsg(-1));
+				(void) elf_errno();
+				continue;
+			}
+			if (sh.sh_type != SHT_SYMTAB)
+				continue;
+			srec_write_symtab(ofd, ofn, e, scn, &sh);
+			break;
+		}
+	}
+
+	if (ecp->flags & SREC_FORCE_S3)
+		dr = '3';
+	else {
+		/*
+		 * Find maximum address size in the first iteration.
+		 */
+		max_addr = 0;
+		scn = NULL;
+		while ((scn = elf_nextscn(e, scn)) != NULL) {
+			if (gelf_getshdr(scn, &sh) == NULL) {
+				warnx("gelf_getshdr failed: %s",
+				    elf_errmsg(-1));
+				(void) elf_errno();
+				continue;
+			}
+			if ((sh.sh_flags & SHF_ALLOC) == 0 ||
+			    sh.sh_type == SHT_NOBITS ||
+			    sh.sh_size == 0)
+				continue;
+			if ((uint64_t) sh.sh_addr > max_addr)
+				max_addr = sh.sh_addr;
+		}
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_nextscn failed: %s", elf_errmsg(elferr));
+
+		if (max_addr <= 0xFFFF)
+			dr = '1';
+		else if (max_addr <= 0xFFFFFF)
+			dr = '2';
+		else
+			dr = '3';
+	}
+
+	if (ecp->flags & SREC_FORCE_LEN) {
+		addr_sz = dr - '0' + 1;
+		if (ecp->srec_len < 1)
+			rlen = 1;
+		else if (ecp->srec_len + addr_sz + 1 > 255)
+			rlen = 255 - (addr_sz + 1);
+		else
+			rlen = ecp->srec_len;
+	} else
+		rlen = 16;
+
+	/* Generate S0 record which contains the output filename. */
+	srec_write_S0(ofd, ofn);
+
+	/* Generate S{1,2,3} data records for section data. */
+	scn = NULL;
+	while ((scn = elf_nextscn(e, scn)) != NULL) {
+		if (gelf_getshdr(scn, &sh) == NULL) {
+			warnx("gelf_getshdr failed: %s", elf_errmsg(-1));
+			(void) elf_errno();
+			continue;
+		}
+		if ((sh.sh_flags & SHF_ALLOC) == 0 ||
+		    sh.sh_type == SHT_NOBITS ||
+		    sh.sh_size == 0)
+			continue;
+		if (sh.sh_addr > 0xFFFFFFFF) {
+			warnx("address space too big for S-Record file");
+			continue;
+		}
+		(void) elf_errno();
+		if ((d = elf_getdata(scn, NULL)) == NULL) {
+			elferr = elf_errno();
+			if (elferr != 0)
+				warnx("elf_getdata failed: %s", elf_errmsg(-1));
+			continue;
+		}
+		if (d->d_buf == NULL || d->d_size == 0)
+			continue;
+		srec_write_Sd(ofd, dr, sh.sh_addr, d->d_buf, d->d_size, rlen);
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		warnx("elf_nextscn failed: %s", elf_errmsg(elferr));
+
+	/* Generate S{7,8,9} end of block record. */
+	if (gelf_getehdr(e, &eh) == NULL)
+		errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
+		    elf_errmsg(-1));
+	srec_write_Se(ofd, eh.e_entry, ecp->flags & SREC_FORCE_S3);
+}
+
+void
+create_elf_from_srec(struct elfcopy *ecp, int ifd)
+{
+	char line[_LINE_BUFSZ], name[_LINE_BUFSZ];
+	uint8_t data[_DATA_BUFSZ];
+	GElf_Ehdr oeh;
+	struct section *s, *shtab;
+	FILE *ifp;
+	uint64_t addr, entry, off, sec_addr;
+	uintmax_t st_value;
+	size_t sz;
+	int _ifd, first, sec_index, in_symtab, symtab_created;
+	char *rlt;
+	char type;
+
+	if ((_ifd = dup(ifd)) < 0)
+		err(EXIT_FAILURE, "dup failed");
+	if ((ifp = fdopen(_ifd, "r")) == NULL)
+		err(EXIT_FAILURE, "fdopen failed");
+
+	/* Create EHDR for output .o file. */
+	if (gelf_newehdr(ecp->eout, ecp->oec) == NULL)
+		errx(EXIT_FAILURE, "gelf_newehdr failed: %s",
+		    elf_errmsg(-1));
+	if (gelf_getehdr(ecp->eout, &oeh) == NULL)
+		errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
+		    elf_errmsg(-1));
+
+	/* Initialise e_ident fields. */
+	oeh.e_ident[EI_CLASS] = ecp->oec;
+	oeh.e_ident[EI_DATA] = ecp->oed;
+	/*
+	 * TODO: Set OSABI according to the OS platform where elfcopy(1)
+	 * was build. (probably)
+	 */
+	oeh.e_ident[EI_OSABI] = ELFOSABI_NONE;
+	oeh.e_machine = ecp->oem;
+	oeh.e_type = ET_REL;
+	oeh.e_entry = 0;
+
+	ecp->flags |= RELOCATABLE;
+
+	/* Create .shstrtab section */
+	init_shstrtab(ecp);
+	ecp->shstrtab->off = 0;
+
+	/* Data sections are inserted after EHDR. */
+	off = gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT);
+	if (off == 0)
+		errx(EXIT_FAILURE, "gelf_fsize() failed: %s", elf_errmsg(-1));
+
+	/* Create data sections. */
+	s = NULL;
+	first = 1;
+	sec_index = 1;
+	sec_addr = entry = 0;
+	while (fgets(line, _LINE_BUFSZ, ifp) != NULL) {
+		sz = 0;
+		if (line[0] == '\r' || line[0] == '\n')
+			continue;
+		if (line[0] == '$' && line[1] == '$') {
+			ecp->flags |= SYMTAB_EXIST;
+			while ((rlt = fgets(line, _LINE_BUFSZ, ifp)) != NULL) {
+				if (line[0] == '$' && line[1] == '$')
+					break;
+			}
+			if (rlt == NULL)
+				break;
+			continue;
+		}
+		if (line[0] != 'S' || line[1] < '0' || line[1] > '9') {
+			warnx("Invalid srec record");
+			continue;
+		}
+		if (srec_read(line, &type, &addr, data, &sz) < 0) {
+			warnx("Invalid srec record or mismatched checksum");
+			continue;
+		}
+		switch (type) {
+		case '1':
+		case '2':
+		case '3':
+			if (sz == 0)
+				break;
+			if (first || sec_addr != addr) {
+				if (s != NULL)
+					finalize_data_section(s);
+				s = new_data_section(ecp, sec_index, off,
+				    addr);
+				if (s == NULL) {
+					warnx("new_data_section failed");
+					break;
+				}
+				sec_index++;
+				sec_addr = addr;
+				first = 0;
+			}
+			append_data(s, data, sz);
+			off += sz;
+			sec_addr += sz;
+			break;
+		case '7':
+		case '8':
+		case '9':
+			entry = addr;
+			break;
+		default:
+			break;
+		}
+	}
+	if (s != NULL)
+		finalize_data_section(s);
+	if (ferror(ifp))
+		warn("fgets failed");
+
+	/* Insert .shstrtab after data sections. */
+	if ((ecp->shstrtab->os = elf_newscn(ecp->eout)) == NULL)
+		errx(EXIT_FAILURE, "elf_newscn failed: %s",
+		    elf_errmsg(-1));
+	insert_to_sec_list(ecp, ecp->shstrtab, 1);
+
+	/* Insert section header table here. */
+	shtab = insert_shtab(ecp, 1);
+
+	/*
+	 * Rescan and create symbol table if we found '$$' section in
+	 * the first scan.
+	 */
+	symtab_created = 0;
+	in_symtab = 0;
+	if (ecp->flags & SYMTAB_EXIST) {
+		if (fseek(ifp, 0, SEEK_SET) < 0) {
+			warn("fseek failed");
+			ecp->flags &= ~SYMTAB_EXIST;
+			goto done;
+		}
+		while (fgets(line, _LINE_BUFSZ, ifp) != NULL) {
+			if (in_symtab) {
+				if (line[0] == '$' && line[1] == '$') {
+					in_symtab = 0;
+					continue;
+				}
+				if (sscanf(line, "%s $%jx", name,
+				    &st_value) != 2) {
+					warnx("Invalid symbolsrec record");
+					continue;
+				}
+				if (!symtab_created) {
+					create_external_symtab(ecp);
+					symtab_created = 1;
+				}
+				add_to_symtab(ecp, name, st_value, 0, SHN_ABS,
+				    ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, 1);
+			}
+			if (line[0] == '$' && line[1] == '$') {
+				in_symtab = 1;
+				continue;
+			}
+		}
+	}
+	if (ferror(ifp))
+		warn("fgets failed");
+	if (symtab_created) {
+		finalize_external_symtab(ecp);
+		create_symtab_data(ecp);
+		/* Count in .symtab and .strtab section headers.  */
+		shtab->sz += gelf_fsize(ecp->eout, ELF_T_SHDR, 2, EV_CURRENT);
+	} else
+		ecp->flags &= ~SYMTAB_EXIST;
+
+done:
+	fclose(ifp);
+
+	/* Set entry point. */
+	oeh.e_entry = entry;
+
+	/*
+	 * Write the underlying ehdr. Note that it should be called
+	 * before elf_setshstrndx() since it will overwrite e->e_shstrndx.
+	 */
+	if (gelf_update_ehdr(ecp->eout, &oeh) == 0)
+		errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s",
+		    elf_errmsg(-1));
+
+	/* Generate section name string table (.shstrtab). */
+	set_shstrtab(ecp);
+
+	/* Update sh_name pointer for each section header entry. */
+	update_shdr(ecp, 0);
+
+	/* Renew oeh to get the updated e_shstrndx. */
+	if (gelf_getehdr(ecp->eout, &oeh) == NULL)
+		errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
+		    elf_errmsg(-1));
+
+	/* Resync section offsets. */
+	resync_sections(ecp);
+
+	/* Store SHDR offset in EHDR. */
+	oeh.e_shoff = shtab->off;
+
+	/* Update ehdr since we modified e_shoff. */
+	if (gelf_update_ehdr(ecp->eout, &oeh) == 0)
+		errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s",
+		    elf_errmsg(-1));
+
+	/* Write out the output elf object. */
+	if (elf_update(ecp->eout, ELF_C_WRITE) < 0)
+		errx(EXIT_FAILURE, "elf_update() failed: %s",
+		    elf_errmsg(-1));
+
+	/* Release allocated resource. */
+	free_elf(ecp);
+}
+
+void
+create_ihex(int ifd, int ofd)
+{
+	Elf *e;
+	Elf_Scn *scn;
+	Elf_Data *d;
+	GElf_Ehdr eh;
+	GElf_Shdr sh;
+	int elferr;
+	uint16_t addr_hi, old_addr_hi;
+
+	if ((e = elf_begin(ifd, ELF_C_READ, NULL)) == NULL)
+		errx(EXIT_FAILURE, "elf_begin() failed: %s",
+		    elf_errmsg(-1));
+
+	old_addr_hi = 0;
+	scn = NULL;
+	while ((scn = elf_nextscn(e, scn)) != NULL) {
+		if (gelf_getshdr(scn, &sh) == NULL) {
+			warnx("gelf_getshdr failed: %s", elf_errmsg(-1));
+			(void) elf_errno();
+			continue;
+		}
+		if ((sh.sh_flags & SHF_ALLOC) == 0 ||
+		    sh.sh_type == SHT_NOBITS ||
+		    sh.sh_size == 0)
+			continue;
+		if (sh.sh_addr > 0xFFFFFFFF) {
+			warnx("address space too big for Intel Hex file");
+			continue;
+		}
+		(void) elf_errno();
+		if ((d = elf_getdata(scn, NULL)) == NULL) {
+			elferr = elf_errno();
+			if (elferr != 0)
+				warnx("elf_getdata failed: %s", elf_errmsg(-1));
+			continue;
+		}
+		if (d->d_buf == NULL || d->d_size == 0)
+			continue;
+		addr_hi = (sh.sh_addr >> 16) & 0xFFFF;
+		if (addr_hi > 0 && addr_hi != old_addr_hi) {
+			/* Write 04 record if addr_hi is new. */
+			old_addr_hi = addr_hi;
+			ihex_write_04(ofd, addr_hi);
+		}
+		ihex_write_00(ofd, sh.sh_addr, d->d_buf, d->d_size);
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		warnx("elf_nextscn failed: %s", elf_errmsg(elferr));
+
+	if (gelf_getehdr(e, &eh) == NULL)
+		errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
+		    elf_errmsg(-1));
+	ihex_write_05(ofd, eh.e_entry);
+	ihex_write_01(ofd);
+}
+
+void
+create_elf_from_ihex(struct elfcopy *ecp, int ifd)
+{
+	char line[_LINE_BUFSZ];
+	uint8_t data[_DATA_BUFSZ];
+	GElf_Ehdr oeh;
+	struct section *s, *shtab;
+	FILE *ifp;
+	uint64_t addr, addr_base, entry, num, off, rec_addr, sec_addr;
+	size_t sz;
+	int _ifd, first, sec_index;
+	char type;
+
+	if ((_ifd = dup(ifd)) < 0)
+		err(EXIT_FAILURE, "dup failed");
+	if ((ifp = fdopen(_ifd, "r")) == NULL)
+		err(EXIT_FAILURE, "fdopen failed");
+
+	/* Create EHDR for output .o file. */
+	if (gelf_newehdr(ecp->eout, ecp->oec) == NULL)
+		errx(EXIT_FAILURE, "gelf_newehdr failed: %s",
+		    elf_errmsg(-1));
+	if (gelf_getehdr(ecp->eout, &oeh) == NULL)
+		errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
+		    elf_errmsg(-1));
+
+	/* Initialise e_ident fields. */
+	oeh.e_ident[EI_CLASS] = ecp->oec;
+	oeh.e_ident[EI_DATA] = ecp->oed;
+	/*
+	 * TODO: Set OSABI according to the OS platform where elfcopy(1)
+	 * was build. (probably)
+	 */
+	oeh.e_ident[EI_OSABI] = ELFOSABI_NONE;
+	oeh.e_machine = ecp->oem;
+	oeh.e_type = ET_REL;
+	oeh.e_entry = 0;
+
+	ecp->flags |= RELOCATABLE;
+
+	/* Create .shstrtab section */
+	init_shstrtab(ecp);
+	ecp->shstrtab->off = 0;
+
+	/* Data sections are inserted after EHDR. */
+	off = gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT);
+	if (off == 0)
+		errx(EXIT_FAILURE, "gelf_fsize() failed: %s", elf_errmsg(-1));
+
+	/* Create data sections. */
+	s = NULL;
+	first = 1;
+	sec_index = 1;
+	addr_base = rec_addr = sec_addr = entry = 0;
+	while (fgets(line, _LINE_BUFSZ, ifp) != NULL) {
+		if (line[0] == '\r' || line[0] == '\n')
+			continue;
+		if (line[0] != ':') {
+			warnx("Invalid ihex record");
+			continue;
+		}
+		if (ihex_read(line, &type, &addr, &num, data, &sz) < 0) {
+			warnx("Invalid ihex record or mismatched checksum");
+			continue;
+		}
+		switch (type) {
+		case '0':
+			/* Data record. */
+			if (sz == 0)
+				break;
+			rec_addr = addr_base + addr;
+			if (first || sec_addr != rec_addr) {
+				if (s != NULL)
+					finalize_data_section(s);
+				s = new_data_section(ecp, sec_index, off,
+				    rec_addr);
+				if (s == NULL) {
+					warnx("new_data_section failed");
+					break;
+				}
+				sec_index++;
+				sec_addr = rec_addr;
+				first = 0;
+			}
+			append_data(s, data, sz);
+			off += sz;
+			sec_addr += sz;
+			break;
+		case '1':
+			/* End of file record. */
+			goto done;
+		case '2':
+			/* Extended segment address record. */
+			addr_base = addr << 4;
+			break;
+		case '3':
+			/* Start segment address record (CS:IP). Ignored. */
+			break;
+		case '4':
+			/* Extended linear address record. */
+			addr_base = num << 16;
+			break;
+		case '5':
+			/* Start linear address record. */
+			entry = num;
+			break;
+		default:
+			break;
+		}
+	}
+done:
+	if (s != NULL)
+		finalize_data_section(s);
+	if (ferror(ifp))
+		warn("fgets failed");
+	fclose(ifp);
+
+	/* Insert .shstrtab after data sections. */
+	if ((ecp->shstrtab->os = elf_newscn(ecp->eout)) == NULL)
+		errx(EXIT_FAILURE, "elf_newscn failed: %s",
+		    elf_errmsg(-1));
+	insert_to_sec_list(ecp, ecp->shstrtab, 1);
+
+	/* Insert section header table here. */
+	shtab = insert_shtab(ecp, 1);
+
+	/* Set entry point. */
+	oeh.e_entry = entry;
+
+	/*
+	 * Write the underlying ehdr. Note that it should be called
+	 * before elf_setshstrndx() since it will overwrite e->e_shstrndx.
+	 */
+	if (gelf_update_ehdr(ecp->eout, &oeh) == 0)
+		errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s",
+		    elf_errmsg(-1));
+
+	/* Generate section name string table (.shstrtab). */
+	set_shstrtab(ecp);
+
+	/* Update sh_name pointer for each section header entry. */
+	update_shdr(ecp, 0);
+
+	/* Renew oeh to get the updated e_shstrndx. */
+	if (gelf_getehdr(ecp->eout, &oeh) == NULL)
+		errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
+		    elf_errmsg(-1));
+
+	/* Resync section offsets. */
+	resync_sections(ecp);
+
+	/* Store SHDR offset in EHDR. */
+	oeh.e_shoff = shtab->off;
+
+	/* Update ehdr since we modified e_shoff. */
+	if (gelf_update_ehdr(ecp->eout, &oeh) == 0)
+		errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s",
+		    elf_errmsg(-1));
+
+	/* Write out the output elf object. */
+	if (elf_update(ecp->eout, ELF_C_WRITE) < 0)
+		errx(EXIT_FAILURE, "elf_update() failed: %s",
+		    elf_errmsg(-1));
+
+	/* Release allocated resource. */
+	free_elf(ecp);
+}
+
+#define	_SEC_NAMESZ	64
+#define	_SEC_INIT_CAP	1024
+
+static struct section *
+new_data_section(struct elfcopy *ecp, int sec_index, uint64_t off,
+    uint64_t addr)
+{
+	char *name;
+
+	if ((name = malloc(_SEC_NAMESZ)) == NULL)
+		errx(EXIT_FAILURE, "malloc failed");
+	snprintf(name, _SEC_NAMESZ, ".sec%d", sec_index);
+
+	return (create_external_section(ecp, name, name, NULL, 0, off,
+		SHT_PROGBITS, ELF_T_BYTE, SHF_ALLOC | SHF_WRITE, 1, addr, 0));
+}
+
+static void
+finalize_data_section(struct section *s)
+{
+	Elf_Data *od;
+
+	if ((od = elf_newdata(s->os)) == NULL)
+		errx(EXIT_FAILURE, "elf_newdata() failed: %s",
+		    elf_errmsg(-1));
+	od->d_align = s->align;
+	od->d_off = 0;
+	od->d_buf = s->buf;
+	od->d_size = s->sz;
+	od->d_version = EV_CURRENT;
+}
+
+static void
+append_data(struct section *s, const void *buf, size_t sz)
+{
+	uint8_t *p;
+
+	if (s->buf == NULL) {
+		s->sz = 0;
+		s->cap = _SEC_INIT_CAP;
+		if ((s->buf = malloc(s->cap)) == NULL)
+			err(EXIT_FAILURE, "malloc failed");
+	}
+
+	while (sz + s->sz > s->cap) {
+		s->cap *= 2;
+		if ((s->buf = realloc(s->buf, s->cap)) == NULL)
+			err(EXIT_FAILURE, "realloc failed");
+	}
+
+	p = s->buf;
+	memcpy(&p[s->sz], buf, sz);
+	s->sz += sz;
+}
+
+static int
+srec_read(const char *line, char *type, uint64_t *addr, uint8_t *data,
+    size_t *sz)
+{
+	uint64_t count, _checksum, num;
+	size_t addr_sz;
+	int checksum, i, len;
+
+	checksum = 0;
+	len = 2;
+	if (read_num(line, &len, &count, 1, &checksum) < 0)
+		return (-1);
+	*type = line[1];
+	switch (*type) {
+	case '0':
+	case '1':
+	case '5':
+	case '9':
+		addr_sz = 2;
+		break;
+	case '2':
+	case '8':
+		addr_sz = 3;
+		break;
+	case '3':
+	case '7':
+		addr_sz = 4;
+		break;
+	default:
+		return (-1);
+	}
+
+	if (read_num(line, &len, addr, addr_sz, &checksum) < 0)
+		return (-1);
+
+	count -= addr_sz + 1;
+	if (*type >= '0' && *type <= '3') {
+		for (i = 0; (uint64_t) i < count; i++) {
+			if (read_num(line, &len, &num, 1, &checksum) < 0)
+				return -1;
+			data[i] = (uint8_t) num;
+		}
+		*sz = count;
+	} else
+		*sz = 0;
+
+	if (read_num(line, &len, &_checksum, 1, NULL) < 0)
+		return (-1);
+
+	if ((int) _checksum != (~checksum & 0xFF))
+		return (-1);
+
+	return (0);
+}
+
+static void
+srec_write_symtab(int ofd, const char *ofn, Elf *e, Elf_Scn *scn, GElf_Shdr *sh)
+{
+	char line[_LINE_BUFSZ];
+	GElf_Sym sym;
+	Elf_Data *d;
+	const char *name;
+	size_t sc;
+	int elferr, i;
+
+#define _WRITE_LINE do {						\
+	if (write(ofd, line, strlen(line)) != (ssize_t) strlen(line)) 	\
+		errx(EXIT_FAILURE, "write failed");				\
+	} while (0)
+
+
+	(void) elf_errno();
+	if ((d = elf_getdata(scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_getdata failed: %s",
+			    elf_errmsg(-1));
+		return;
+	}
+	if (d->d_buf == NULL || d->d_size == 0)
+		return;
+
+	snprintf(line, sizeof(line), "$$ %s\r\n", ofn);
+	_WRITE_LINE;
+	sc = d->d_size / sh->sh_entsize;
+	for (i = 1; (size_t) i < sc; i++) {
+		if (gelf_getsym(d, i, &sym) != &sym) {
+			warnx("gelf_getsym failed: %s", elf_errmsg(-1));
+			continue;
+		}
+		if (GELF_ST_TYPE(sym.st_info) == STT_SECTION ||
+		    GELF_ST_TYPE(sym.st_info) == STT_FILE)
+			continue;
+		if ((name = elf_strptr(e, sh->sh_link, sym.st_name)) == NULL) {
+			warnx("elf_strptr failed: %s", elf_errmsg(-1));
+			continue;
+		}
+		snprintf(line, sizeof(line), "  %s $%jx\r\n", name,
+		    (uintmax_t) sym.st_value);
+		_WRITE_LINE;
+	}
+	snprintf(line, sizeof(line), "$$ \r\n");
+	_WRITE_LINE;
+
+#undef	_WRITE_LINE
+}
+
+static void
+srec_write_S0(int ofd, const char *ofn)
+{
+
+	srec_write(ofd, '0', 0, ofn, strlen(ofn));
+}
+
+static void
+srec_write_Sd(int ofd, char dr, uint64_t addr, const void *buf, size_t sz,
+    size_t rlen)
+{
+	const uint8_t *p, *pe;
+
+	p = buf;
+	pe = p + sz;
+	while (pe - p >= (int) rlen) {
+		srec_write(ofd, dr, addr, p, rlen);
+		addr += rlen;
+		p += rlen;
+	}
+	if (pe - p > 0)
+		srec_write(ofd, dr, addr, p, pe - p);
+}
+
+static void
+srec_write_Se(int ofd, uint64_t e_entry, int forceS3)
+{
+	char er;
+
+	if (e_entry > 0xFFFFFFFF) {
+		warnx("address space too big for S-Record file");
+		return;
+	}
+
+	if (forceS3)
+		er = '7';
+	else {
+		if (e_entry <= 0xFFFF)
+			er = '9';
+		else if (e_entry <= 0xFFFFFF)
+			er = '8';
+		else
+			er = '7';
+	}
+
+	srec_write(ofd, er, e_entry, NULL, 0);
+}
+
+static void
+srec_write(int ofd, char type, uint64_t addr, const void *buf, size_t sz)
+{
+	char line[_LINE_BUFSZ];
+	const uint8_t *p, *pe;
+	int len, addr_sz, checksum;
+
+	if (type == '0' || type == '1' || type == '5' || type == '9')
+		addr_sz = 2;
+	else if (type == '2' || type == '8')
+		addr_sz = 3;
+	else
+		addr_sz = 4;
+
+	checksum = 0;
+	line[0] = 'S';
+	line[1] = type;
+	len = 2;
+	write_num(line, &len, addr_sz + sz + 1, 1, &checksum);
+	write_num(line, &len, addr, addr_sz, &checksum);
+	for (p = buf, pe = p + sz; p < pe; p++)
+		write_num(line, &len, *p, 1, &checksum);
+	write_num(line, &len, ~checksum & 0xFF, 1, NULL);
+	line[len++] = '\r';
+	line[len++] = '\n';
+	if (write(ofd, line, len) != (ssize_t) len)
+		err(EXIT_FAILURE, "write failed");
+}
+
+static void
+ihex_write_00(int ofd, uint64_t addr, const void *buf, size_t sz)
+{
+	uint16_t addr_hi, old_addr_hi;
+	const uint8_t *p, *pe;
+
+	old_addr_hi = (addr >> 16) & 0xFFFF;
+	p = buf;
+	pe = p + sz;
+	while (pe - p >= 16) {
+		ihex_write(ofd, 0, addr, 0, p, 16);
+		addr += 16;
+		p += 16;
+		addr_hi = (addr >> 16) & 0xFFFF;
+		if (addr_hi != old_addr_hi) {
+			old_addr_hi = addr_hi;
+			ihex_write_04(ofd, addr_hi);
+		}
+	}
+	if (pe - p > 0)
+		ihex_write(ofd, 0, addr, 0, p, pe - p);
+}
+
+static int
+ihex_read(const char *line, char *type, uint64_t *addr, uint64_t *num,
+    uint8_t *data, size_t *sz)
+{
+	uint64_t count, _checksum;
+	int checksum, i, len;
+
+	*sz = 0;
+	checksum = 0;
+	len = 1;
+	if (read_num(line, &len, &count, 1, &checksum) < 0)
+		return (-1);
+	if (read_num(line, &len, addr, 2, &checksum) < 0)
+		return (-1);
+	if (line[len++] != '0')
+		return (-1);
+	*type = line[len++];
+	checksum += *type - '0';
+	switch (*type) {
+	case '0':
+		for (i = 0; (uint64_t) i < count; i++) {
+			if (read_num(line, &len, num, 1, &checksum) < 0)
+				return (-1);
+			data[i] = (uint8_t) *num;
+		}
+		*sz = count;
+		break;
+	case '1':
+		if (count != 0)
+			return (-1);
+		break;
+	case '2':
+	case '4':
+		if (count != 2)
+			return (-1);
+		if (read_num(line, &len, num, 2, &checksum) < 0)
+			return (-1);
+		break;
+	case '3':
+	case '5':
+		if (count != 4)
+			return (-1);
+		if (read_num(line, &len, num, 4, &checksum) < 0)
+			return (-1);
+		break;
+	default:
+		return (-1);
+	}
+
+	if (read_num(line, &len, &_checksum, 1, &checksum) < 0)
+		return (-1);
+
+	if ((checksum & 0xFF) != 0) {
+		return (-1);
+	}
+
+	return (0);
+}
+
+static void
+ihex_write_01(int ofd)
+{
+
+	ihex_write(ofd, 1, 0, 0, NULL, 0);
+}
+
+static void
+ihex_write_04(int ofd, uint16_t addr)
+{
+
+	ihex_write(ofd, 4, 0, addr, NULL, 2);
+}
+
+static void
+ihex_write_05(int ofd, uint64_t e_entry)
+{
+
+	if (e_entry > 0xFFFFFFFF) {
+		warnx("address space too big for Intel Hex file");
+		return;
+	}
+
+	ihex_write(ofd, 5, 0, e_entry, NULL, 4);
+}
+
+static void
+ihex_write(int ofd, int type, uint64_t addr, uint64_t num, const void *buf,
+    size_t sz)
+{
+	char line[_LINE_BUFSZ];
+	const uint8_t *p, *pe;
+	int len, checksum;
+
+	if (sz > 16)
+		errx(EXIT_FAILURE, "Internal: ihex_write() sz too big");
+	checksum = 0;
+	line[0] = ':';
+	len = 1;
+	write_num(line, &len, sz, 1, &checksum);
+	write_num(line, &len, addr, 2, &checksum);
+	write_num(line, &len, type, 1, &checksum);
+	if (sz > 0) {
+		if (buf != NULL) {
+			for (p = buf, pe = p + sz; p < pe; p++)
+				write_num(line, &len, *p, 1, &checksum);
+		} else
+			write_num(line, &len, num, sz, &checksum);
+	}
+	write_num(line, &len, (~checksum + 1) & 0xFF, 1, NULL);
+	line[len++] = '\r';
+	line[len++] = '\n';
+	if (write(ofd, line, len) != (ssize_t) len)
+		err(EXIT_FAILURE, "write failed");
+}
+
+static int
+read_num(const char *line, int *len, uint64_t *num, size_t sz, int *checksum)
+{
+	uint8_t b;
+
+	*num = 0;
+	for (; sz > 0; sz--) {
+		if (!ishexdigit(line[*len]) || !ishexdigit(line[*len + 1]))
+			return (-1);
+		b = (hex_value(line[*len]) << 4) | hex_value(line[*len + 1]);
+		*num = (*num << 8) | b;
+		*len += 2;
+		if (checksum != NULL)
+			*checksum = (*checksum + b) & 0xFF;
+	}
+
+	return (0);
+}
+
+static void
+write_num(char *line, int *len, uint64_t num, size_t sz, int *checksum)
+{
+	uint8_t b;
+
+	for (; sz > 0; sz--) {
+		b = (num >> ((sz - 1) * 8)) & 0xFF;
+		line[*len] = hex_digit((b >> 4) & 0xF);
+		line[*len + 1] = hex_digit(b & 0xF);
+		*len += 2;
+		if (checksum != NULL)
+			*checksum = (*checksum + b) & 0xFF;
+	}
+}
+
+static char
+hex_digit(uint8_t n)
+{
+
+	return ((n < 10) ? '0' + n : 'A' + (n - 10));
+}
+
+static int
+hex_value(int x)
+{
+
+	if (isdigit(x))
+		return (x - '0');
+	else if (x >= 'a' && x <= 'f')
+		return (x - 'a' + 10);
+	else
+		return (x - 'A' + 10);
+}
+
+static int
+ishexdigit(int x)
+{
+
+	if (isdigit(x))
+		return (1);
+	if ((x >= 'a' && x <= 'f') || (x >= 'A' && x <= 'F'))
+		return (1);
+
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/elfcopy/binary.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,293 @@
+/*-
+ * Copyright (c) 2010,2011 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <err.h>
+#include <gelf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "elfcopy.h"
+
+ELFTC_VCSID("$Id: binary.c 3611 2018-04-16 21:35:18Z jkoshy $");
+
+/*
+ * Convert ELF object to `binary'. Sections with SHF_ALLOC flag set
+ * are copied to the result binary. The relative offsets for each section
+ * are retained, so the result binary file might contain "holes".
+ */
+void
+create_binary(int ifd, int ofd)
+{
+	Elf *e;
+	Elf_Scn *scn;
+	Elf_Data *d;
+	GElf_Shdr sh;
+	off_t base, off;
+	int elferr;
+
+	if ((e = elf_begin(ifd, ELF_C_READ, NULL)) == NULL)
+		errx(EXIT_FAILURE, "elf_begin() failed: %s",
+		    elf_errmsg(-1));
+
+	base = 0;
+	if (lseek(ofd, base, SEEK_SET) < 0)
+		err(EXIT_FAILURE, "lseek failed");
+
+	/*
+	 * Find base offset in the first iteration.
+	 */
+	base = -1;
+	scn = NULL;
+	while ((scn = elf_nextscn(e, scn)) != NULL) {
+		if (gelf_getshdr(scn, &sh) == NULL) {
+			warnx("gelf_getshdr failed: %s", elf_errmsg(-1));
+			(void) elf_errno();
+			continue;
+		}
+		if ((sh.sh_flags & SHF_ALLOC) == 0 ||
+		    sh.sh_type == SHT_NOBITS ||
+		    sh.sh_size == 0)
+			continue;
+		if (base == -1 || (off_t) sh.sh_offset < base)
+			base = sh.sh_offset;
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		warnx("elf_nextscn failed: %s", elf_errmsg(elferr));
+
+	if (base == -1)
+		return;
+
+	/*
+	 * Write out sections in the second iteration.
+	 */
+	scn = NULL;
+	while ((scn = elf_nextscn(e, scn)) != NULL) {
+		if (gelf_getshdr(scn, &sh) == NULL) {
+			warnx("gelf_getshdr failed: %s", elf_errmsg(-1));
+			(void) elf_errno();
+			continue;
+		}
+		if ((sh.sh_flags & SHF_ALLOC) == 0 ||
+		    sh.sh_type == SHT_NOBITS ||
+		    sh.sh_size == 0)
+			continue;
+		(void) elf_errno();
+		if ((d = elf_rawdata(scn, NULL)) == NULL) {
+			elferr = elf_errno();
+			if (elferr != 0)
+				warnx("elf_rawdata failed: %s", elf_errmsg(-1));
+			continue;
+		}
+		if (d->d_buf == NULL || d->d_size == 0)
+			continue;
+
+		/* lseek to section offset relative to `base'. */
+		off = sh.sh_offset - base;
+		if (lseek(ofd, off, SEEK_SET) < 0)
+			err(EXIT_FAILURE, "lseek failed");
+
+		/* Write out section contents. */
+		if (write(ofd, d->d_buf, d->d_size) != (ssize_t) d->d_size)
+			err(EXIT_FAILURE, "write failed");
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		warnx("elf_nextscn failed: %s", elf_errmsg(elferr));
+}
+
+#define	_SYMBOL_NAMSZ	1024
+
+/*
+ * Convert `binary' to ELF object. The input `binary' is converted to
+ * a relocatable (.o) file, a few symbols will also be created to make
+ * it easier to access the binary data in other compilation units.
+ */
+void
+create_elf_from_binary(struct elfcopy *ecp, int ifd, const char *ifn)
+{
+	char name[_SYMBOL_NAMSZ];
+	struct section *sec, *sec_temp, *shtab;
+	struct stat sb;
+	GElf_Ehdr oeh;
+	GElf_Shdr sh;
+	void *content;
+	uint64_t off, data_start, data_end, data_size;
+	char *sym_basename, *p;
+
+	/* Reset internal section list. */
+	if (!TAILQ_EMPTY(&ecp->v_sec))
+		TAILQ_FOREACH_SAFE(sec, &ecp->v_sec, sec_list, sec_temp) {
+			TAILQ_REMOVE(&ecp->v_sec, sec, sec_list);
+			free(sec);
+		}
+
+	if (fstat(ifd, &sb) == -1)
+		err(EXIT_FAILURE, "fstat failed");
+
+	/* Read the input binary file to a internal buffer. */
+	if ((content = malloc(sb.st_size)) == NULL)
+		err(EXIT_FAILURE, "malloc failed");
+	if (read(ifd, content, sb.st_size) != sb.st_size)
+		err(EXIT_FAILURE, "read failed");
+
+	/*
+	 * TODO: copy the input binary to output binary verbatim if -O is not
+	 * specified.
+	 */
+
+	/* Create EHDR for output .o file. */
+	if (gelf_newehdr(ecp->eout, ecp->oec) == NULL)
+		errx(EXIT_FAILURE, "gelf_newehdr failed: %s",
+		    elf_errmsg(-1));
+	if (gelf_getehdr(ecp->eout, &oeh) == NULL)
+		errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
+		    elf_errmsg(-1));
+
+	/* Initialise e_ident fields. */
+	oeh.e_ident[EI_CLASS] = ecp->oec;
+	oeh.e_ident[EI_DATA] = ecp->oed;
+	/*
+	 * TODO: Set OSABI according to the OS platform where elfcopy(1)
+	 * was build. (probably)
+	 */
+	oeh.e_ident[EI_OSABI] = ELFOSABI_NONE;
+	oeh.e_machine = ecp->oem;
+	oeh.e_type = ET_REL;
+	oeh.e_entry = 0;
+
+	ecp->flags |= RELOCATABLE;
+
+	/* Create .shstrtab section */
+	init_shstrtab(ecp);
+	ecp->shstrtab->off = 0;
+
+	/*
+	 * Create `.data' section which contains the binary data. The
+	 * section is inserted immediately after EHDR.
+	 */
+	off = gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT);
+	if (off == 0)
+		errx(EXIT_FAILURE, "gelf_fsize() failed: %s", elf_errmsg(-1));
+	(void) create_external_section(ecp, ".data", NULL, content, sb.st_size,
+	    off, SHT_PROGBITS, ELF_T_BYTE, SHF_ALLOC | SHF_WRITE, 1, 0, 1);
+
+	/* Insert .shstrtab after .data section. */
+	if ((ecp->shstrtab->os = elf_newscn(ecp->eout)) == NULL)
+		errx(EXIT_FAILURE, "elf_newscn failed: %s",
+		    elf_errmsg(-1));
+	insert_to_sec_list(ecp, ecp->shstrtab, 1);
+
+	/* Insert section header table here. */
+	shtab = insert_shtab(ecp, 1);
+
+	/* Count in .symtab and .strtab section headers.  */
+	shtab->sz += gelf_fsize(ecp->eout, ELF_T_SHDR, 2, EV_CURRENT);
+
+	if ((sym_basename = strdup(ifn)) == NULL)
+		err(1, "strdup");
+	for (p = sym_basename; *p != '\0'; p++)
+		if (!isalnum(*p & 0xFF))
+			*p = '_';
+#define	_GEN_SYMNAME(S) do {						\
+	snprintf(name, sizeof(name), "%s%s%s", "_binary_", sym_basename, S); \
+} while (0)
+
+	/*
+	 * Create symbol table.
+	 */
+	create_external_symtab(ecp);
+	data_start = 0;
+	data_end = data_start + sb.st_size;
+	data_size = sb.st_size;
+	_GEN_SYMNAME("_start");
+	add_to_symtab(ecp, name, data_start, 0, 1,
+	    ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, 1);
+	_GEN_SYMNAME("_end");
+	add_to_symtab(ecp, name, data_end, 0, 1,
+	    ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, 1);
+	_GEN_SYMNAME("_size");
+	add_to_symtab(ecp, name, data_size, 0, SHN_ABS,
+	    ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, 1);
+	finalize_external_symtab(ecp);
+	create_symtab_data(ecp);
+#undef	_GEN_SYMNAME
+	free(sym_basename);
+
+	/*
+	 * Write the underlying ehdr. Note that it should be called
+	 * before elf_setshstrndx() since it will overwrite e->e_shstrndx.
+	 */
+	if (gelf_update_ehdr(ecp->eout, &oeh) == 0)
+		errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s",
+		    elf_errmsg(-1));
+
+	/* Generate section name string table (.shstrtab). */
+	ecp->flags |= SYMTAB_EXIST;
+	set_shstrtab(ecp);
+
+	/* Update sh_name pointer for each section header entry. */
+	update_shdr(ecp, 0);
+
+	/* Properly set sh_link field of .symtab section. */
+	if (gelf_getshdr(ecp->symtab->os, &sh) == NULL)
+		errx(EXIT_FAILURE, "692 gelf_getshdr() failed: %s",
+		    elf_errmsg(-1));
+	sh.sh_link = elf_ndxscn(ecp->strtab->os);
+	if (!gelf_update_shdr(ecp->symtab->os, &sh))
+		errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s",
+		    elf_errmsg(-1));
+
+	/* Renew oeh to get the updated e_shstrndx. */
+	if (gelf_getehdr(ecp->eout, &oeh) == NULL)
+		errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
+		    elf_errmsg(-1));
+
+	/* Resync section offsets. */
+	resync_sections(ecp);
+
+	/* Store SHDR offset in EHDR. */
+	oeh.e_shoff = shtab->off;
+
+	/* Update ehdr since we modified e_shoff. */
+	if (gelf_update_ehdr(ecp->eout, &oeh) == 0)
+		errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s",
+		    elf_errmsg(-1));
+
+	/* Write out the output elf object. */
+	if (elf_update(ecp->eout, ELF_C_WRITE) < 0)
+		errx(EXIT_FAILURE, "elf_update() failed: %s",
+		    elf_errmsg(-1));
+
+	/* Release allocated resource. */
+	free(content);
+	free_elf(ecp);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/elfcopy/elfcopy.1	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,369 @@
+.\" Copyright (c) 2008-2009,2011 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elfcopy.1 3565 2017-08-31 02:24:19Z emaste $
+.\"
+.Dd August 30, 2017
+.Os
+.Dt ELFCOPY 1
+.Sh NAME
+.Nm elfcopy ,
+.Nm objcopy
+.Nd copy and translate object files
+.Sh SYNOPSIS
+.Nm
+.Op Fl I Ar objformat | Fl s Ar objformat | Fl -input-target= Ns Ar objformat
+.Op Fl K Ar symbolname | Fl -keep-symbol= Ns Ar symbolname
+.Op Fl L Ar symbolname | Fl -localize-symbol= Ns Ar symbolname
+.Op Fl N Ar symbolname | Fl -strip-symbol= Ns Ar symbolname
+.Op Fl O Ar objformat | Fl -output-target= Ns Ar objformat
+.Op Fl R Ar sectionname | Fl -remove-section= Ns Ar sectionname
+.Op Fl S | Fl -strip-all
+.Op Fl V | Fl -version
+.Op Fl W Ar symbolname | Fl -weaken-symbol= Ns Ar symbolname
+.Op Fl X | Fl -discard-locals
+.Op Fl d | Fl g | Fl -strip-debug
+.Op Fl h | Fl -help
+.Op Fl j Ar sectionname | Fl -only-section= Ns Ar sectionname
+.Op Fl p | Fl -preserve-dates
+.Op Fl w | Fl -wildcard
+.Op Fl x | Fl -discard-all
+.Op Fl -add-gnu-debuglink Ns = Ns Ar filename
+.Op Fl -add-section Ar sectionname Ns = Ns Ar filename
+.Oo
+.Fl -adjust-section-vma Ar section Ns {+|-|=} Ns Ar val |
+.Fl -change-section-address Ar section Ns {+|-|=} Ns Ar val
+.Oc
+.Oo
+.Fl -adjust-start Ns = Ns Ar increment |
+.Fl -change-start Ns = Ns Ar increment
+.Oc
+.Oo
+.Fl -adjust-vma Ns = Ns Ar increment |
+.Fl -change-addresses Ns = Ns Ar increment
+.Oc
+.Op Fl -adjust-warnings | Fl -change-warnings
+.Op Fl -change-section-lma Ar section Ns {+|-|=} Ns Ar val
+.Op Fl -change-section-vma Ar section Ns {+|-|=} Ns Ar val
+.Op Fl -extract-dwo
+.Op Fl -gap-fill Ns = Ns Ar val
+.Op Fl -globalize-symbol Ns = Ns ar symbolname
+.Op Fl -globalize-symbols Ns = Ns Ar filename
+.Op Fl -localize-hidden
+.Op Fl -localize-symbols Ns = Ns Ar filename
+.Op Fl -no-adjust-warnings | Fl -no-change-warnings
+.Op Fl -only-keep-debug
+.Op Fl -pad-to Ns = Ns Ar address
+.Op Fl -prefix-alloc-sections Ns = Ns Ar string
+.Op Fl -prefix-sections Ns = Ns Ar string
+.Op Fl -prefix-symbols Ns = Ns Ar string
+.Op Fl -rename-section Ar oldname Ns = Ns Ar newname Ns Op Ar ,flags
+.Op Fl -set-section-flags Ar sectionname Ns = Ns Ar flags
+.Op Fl -set-start Ns = Ns Ar address
+.Op Fl -srec-forceS3
+.Op Fl -srec-len Ns = Ns Ar val
+.Op Fl -strip-dwo
+.Op Fl -strip-symbols= Ns Ar filename
+.Op Fl -strip-unneeded
+.Ar infile
+.Op Ar outfile
+.Sh DESCRIPTION
+The
+.Nm
+utility copies the content of the binary object named by argument
+.Ar infile
+to that named by argument
+.Ar outfile ,
+transforming it according to the command line options specified.
+If argument
+.Ar outfile
+is not specified,
+.Nm
+will create a temporary file and will subsequently rename it as
+.Ar infile .
+.Pp
+The
+.Nm
+utility supports the following options:
+.Bl -tag -width indent
+.It Fl I Ar objformat | Fl s Ar objformat | Fl -input-target= Ns Ar objformat
+Specify that the input file named by the argument
+.Ar infile
+is in the object format specified by the argument
+.Ar objformat .
+.It Fl K Ar symbolname | Fl -keep-symbol= Ns Ar symbolname
+Copy the symbol named by argument
+.Ar symbolname
+to the output.
+.It Fl L Ar symbolname | Fl -localize-symbol= Ns Ar symbolname
+Make the symbol named by argument
+.Ar symbolname
+local to the output file.
+.It Fl N Ar symbol | Fl -strip-symbol= Ns Ar symbolname
+Do not copy the symbol named by argument
+.Ar symbolname
+to the output.
+.It Fl O Ar objformat | Fl -output-target= Ns Ar objformat
+Write the output file using the object format specified in argument
+.Ar objformat .
+The argument
+.Ar objformat
+should be one of the target names recognized by
+.Xr elftc_bfd_find_target 3 .
+.It Fl R Ar sectionname | Fl -remove-section= Ns Ar sectionname
+Remove any section with name
+.Ar sectionname
+from the output file.
+.It Fl S | Fl -strip-all
+Do not copy symbol and relocation information to the target file.
+.It Fl V | Fl -version
+Print a version identifier and exit.
+.It Fl W Ar symbolname | Fl -weaken-symbol= Ns Ar symbolname
+Mark the symbol named by argument
+.Ar symbolname
+as weak in the output.
+.It Fl X | Fl -discard-locals
+Do not copy compiler generated local symbols to the output.
+.It Fl d | Fl g | Fl -strip-debug
+Do not copy debugging information to the target file.
+.It Fl h | Fl -help
+Display a help message and exit.
+.It Fl j Ar sectionname | Fl -only-section= Ns Ar sectionname
+Copy only the section named by argument
+.Ar sectionname
+to the output.
+.It Fl p | Fl -preserve-dates
+Set the access and modification times of the output file to the
+same as those of the input.
+.It Fl w | Fl -wildcard
+Use shell-style patterns to name symbols.
+The following meta-characters are recognized in patterns:
+.Bl -tag -width "...." -compact
+.It Li !
+If this is the first character of the pattern, invert the sense of the
+pattern match.
+.It Li *
+Matches any string of characters in a symbol name.
+.It Li ?
+Matches zero or one character in a symbol name.
+.It Li [
+Mark the start of a character class.
+.It Li \e
+Remove the special meaning of the next character in the pattern.
+.It Li ]
+Mark the end of a character class.
+.El
+.It Fl x | Fl -discard-all
+Do not copy non-global symbols to the output.
+.It Fl -add-gnu-debuglink Ns = Ns Ar filename
+Create a .gnu_debuglink section in the output file that references the
+debug data in
+.Ar filename .
+.It Fl -add-section Ar sectionname Ns = Ns Ar filename
+Add a new section to the output file with name
+.Ar sectionname .
+The contents of the section are taken from the file named by
+argument
+.Ar filename .
+The size of the section will be the number of bytes in file
+.Ar filename .
+.It Xo
+.Fl -adjust-section-vma Ar section Ns {+|-|=} Ns Ar val |
+.Fl -change-section-address Ar section Ns {+|-|=} Ns Ar val
+.Xc
+Depending on the operator specified, increase, decrease or set both
+the virtual memory address and the load memory address of the section
+named by the argument
+.Ar section .
+The argument
+.Ar val
+specifies the desired increment, decrement or new value for the
+address.
+.It Xo
+.Fl -adjust-start Ns = Ns Ar increment |
+.Fl -change-start Ns = Ns Ar increment
+.Xc
+Increase the entry point address of the output ELF object by the value
+specified in the argument
+.Ar increment .
+.It Xo
+.Fl -adjust-vma Ns = Ns Ar increment |
+.Fl -change-addresses Ns = Ns Ar increment
+.Xc
+Increase the virtual memory address and the load memory address of all
+sections by the value specified by the argument
+.Ar increment .
+.It Fl -adjust-warnings | Fl -change-warnings
+Issue a warning if the section specified by the options
+.Fl -change-section-address ,
+.Fl -change-section-lma
+or
+.Fl -change-section-vma
+does not exist in the input object.
+This is the default.
+.It Fl -change-section-lma Ar section Ns {+|-|=} Ns Ar val
+Change or set the load memory address of the section named by the
+argument
+.Ar section .
+Depending on the operator specified, the value in argument
+.Ar val
+will be used as an increment, a decrement or as the new value
+of the load memory address.
+.It Fl -change-section-vma Ar section Ns {+|-|=} Ns Ar val
+Change or set the virtual memory address of the section named by the
+argument
+.Ar section .
+Depending on the operator specified, the value in argument
+.Ar val
+will be used as an increment, a decrement or as the new value
+of the virtual memory address.
+.It Fl -extract-dwo
+Copy only .dwo debug sections to the output file.
+.It Fl -gap-fill Ns = Ns Ar val
+Fill the gaps between sections with the byte value specified by
+the argument
+.Ar val .
+.It Fl -globalize-symbol Ns = Ns Ar symbolname
+Make the symbol named by argument
+.Ar symbolname
+global, so that it is visible outside of the file in which it is defined.
+.It Fl -globalize-symbols Ns = Ns Ar filename
+Make each symbol listed in the file specified by
+.Ar filename
+global.
+.It Fl -localize-hidden
+Make all hidden symbols local to the output file.
+This includes symbols with internal visiblity.
+.It Fl -localize-symbols Ns = Ns Ar filename
+Make each symbol listed in the file specified by
+.Ar filename
+local to the output file.
+.It Fl -no-adjust-warnings | Fl -no-change-warnings
+Do not issue a warning if the section specified by the options
+.Fl -change-section-address ,
+.Fl -change-section-lma
+or
+.Fl -change-section-vma
+is missing in the input object.
+.It Fl -only-keep-debug
+Copy only debugging information to the output file.
+.It Fl -pad-to Ns = Ns Ar address
+Pad the load memory address of the output object to the value
+specified by the argument
+.Ar address
+by increasing the size of the section with the highest load memory
+address.
+.It Fl -prefix-alloc-sections Ns = Ns Ar string
+Prefix the section names of all the allocated sections with
+.Ar string .
+.It Fl -prefix-sections Ns = Ns Ar string
+Prefix the section names of all the sections with
+.Ar string .
+.It Fl -prefix-symbols Ns = Ns Ar string
+Prefix the symbol names of all the symbols with
+.Ar string .
+.It Fl -rename-section Ar oldname Ns = Ns Ar newname Ns Op Ar ,flags
+Rename the section named by argument
+.Ar oldname
+to
+.Ar newname ,
+optionally changing the sections flags to that specified by argument
+.Ar flags .
+Allowed values for the argument
+.Ar flags
+are as for option
+.Fl -set-section-flags
+below.
+.It Fl -set-section-flags Ar sectionname Ns = Ns Ar flags
+Set the flags for the section named by argument
+.Ar sectionname
+to those specified by argument
+.Ar flags .
+Argument
+.Ar flags
+is a comma separated list of the following flag names:
+.Bl -tag -width "readonly" -compact
+.It alloc
+The section occupies space in the output file.
+.It code
+The section contains machine instructions.
+.It contents
+This flag is accepted but is ignored.
+.It data
+The section contains writeable data.
+.It debug
+The section holds debugging information.
+.It load
+The section is loadable.
+.It noload
+The section should not be loaded into memory.
+.It readonly
+The section is not writable.
+.It rom
+The section contains ROM'able contents.
+.It share
+This flag is accepted but is ignored.
+.El
+.It Fl -set-start Ns = Ns Ar address
+Set the start address of the output ELF object to the value specified
+by the argument
+.Ar address .
+.It Fl -srec-forceS3
+Only generate S-records of type
+.Dq S3 .
+This option is only meaningful when the output target is set to
+.Dq srec .
+.It Fl -srec-len Ns = Ns Ar val
+Set the maximum length of an S-record line to
+.Ar val .
+This option is only meaningful when the output target is set to
+.Dq srec .
+.It Fl -strip-dwo
+Do not copy .dwo debug sections to the output file.
+.It Fl -strip-symbols= Ns Ar filename
+Do not copy any of the symbols specified by
+.Ar filename
+to the output.
+.It Fl -strip-unneeded
+Do not copy symbols that are not needed for relocation processing.
+.El
+.Sh DIAGNOSTICS
+.Ex -std
+.Sh SEE ALSO
+.Xr ar 1 ,
+.Xr ld 1 ,
+.Xr mcs 1 ,
+.Xr strip 1 ,
+.Xr elf 3 ,
+.Xr elftc_bfd_find_target 3 ,
+.Xr ar 5 ,
+.Xr elf 5
+.Sh COMPATIBILITY
+The
+.Nm
+utility is expected to be option compatible with GNU
+.Nm objcopy .
+.Sh HISTORY
+.Nm
+has been implemented by
+.An Kai Wang Aq Mt kaiwang27@users.sourceforge.net .
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/elfcopy/elfcopy.h	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,321 @@
+/*-
+ * Copyright (c) 2007-2013 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: elfcopy.h 3446 2016-05-03 01:31:17Z emaste $
+ */
+
+#include <sys/queue.h>
+#include <gelf.h>
+#include <libelftc.h>
+
+#include "_elftc.h"
+
+/*
+ * User specified symbol operation (strip, keep, localize, globalize,
+ * weaken, rename, etc).
+ */
+struct symop {
+	const char	*name;
+	const char	*newname;
+
+#define SYMOP_KEEP	0x0001U
+#define SYMOP_STRIP	0x0002U
+#define SYMOP_GLOBALIZE	0x0004U
+#define SYMOP_LOCALIZE	0x0008U
+#define SYMOP_KEEPG	0x0010U
+#define SYMOP_WEAKEN	0x0020U
+#define SYMOP_REDEF	0x0040U
+
+	unsigned int	op;
+
+	STAILQ_ENTRY(symop) symop_list;
+};
+
+/* File containing symbol list. */
+struct symfile {
+	dev_t		 dev;
+	ino_t		 ino;
+	size_t		 size;
+	char		*data;
+	unsigned int	 op;
+
+	STAILQ_ENTRY(symfile) symfile_list;
+};
+
+/* Sections to copy/remove/rename/... */
+struct sec_action {
+	const char	*name;
+	const char	*addopt;
+	const char	*newname;
+	const char	*string;
+	uint64_t	 lma;
+	uint64_t	 vma;
+	int64_t		 lma_adjust;
+	int64_t		 vma_adjust;
+
+#define	SF_ALLOC	0x0001U
+#define	SF_LOAD		0x0002U
+#define	SF_NOLOAD	0x0004U
+#define	SF_READONLY	0x0008U
+#define	SF_DEBUG	0x0010U
+#define	SF_CODE		0x0020U
+#define	SF_DATA		0x0040U
+#define	SF_ROM		0x0080U
+#define	SF_SHARED	0X0100U
+#define	SF_CONTENTS	0x0200U
+
+	int	flags;
+	int	add;
+	int	append;
+	int	compress;
+	int	copy;
+	int	print;
+	int	remove;
+	int	rename;
+	int	setflags;
+	int	setlma;
+	int	setvma;
+
+	STAILQ_ENTRY(sec_action) sac_list;
+};
+
+/* Sections to add from file. */
+struct sec_add {
+	char	*name;
+	char	*content;
+	size_t	 size;
+
+	STAILQ_ENTRY(sec_add) sadd_list;
+};
+
+struct segment;
+
+/* Internal data structure for sections. */
+struct section {
+	struct segment	*seg;	/* containing segment */
+	struct segment	*seg_tls; /* tls segment */
+	const char	*name;	/* section name */
+	char		*newname; /* new section name */
+	Elf_Scn		*is;	/* input scn */
+	Elf_Scn		*os;	/* output scn */
+	void		*buf;	/* section content */
+	uint8_t		*pad;	/* section padding */
+	uint64_t	 off;	/* section offset */
+	uint64_t	 sz;	/* section size */
+	uint64_t	 cap;	/* section capacity */
+	uint64_t	 align;	/* section alignment */
+	uint64_t	 type;	/* section type */
+	uint64_t	 flags;	/* section flags */
+	uint64_t	 vma;	/* section virtual addr */
+	uint64_t	 lma;	/* section load addr */
+	uint64_t	 pad_sz;/* section padding size */
+	int		 loadable; /* whether loadable */
+	int		 pseudo;
+	int		 nocopy;
+
+	TAILQ_ENTRY(section) sec_list;	/* next section */
+};
+
+/* Internal data structure for segments. */
+struct segment {
+	uint64_t	vaddr;	/* virtual addr (VMA) */
+	uint64_t	paddr;	/* physical addr (LMA) */
+	uint64_t	off;	/* file offset */
+	uint64_t	fsz;	/* file size */
+	uint64_t	msz;	/* memory size */
+	uint64_t	type;	/* segment type */
+	int		remove;	/* whether remove */
+	int		nsec;	/* number of sections contained */
+	struct section **v_sec;	/* list of sections contained */
+
+	STAILQ_ENTRY(segment) seg_list; /* next segment */
+};
+
+/*
+ * In-memory representation of ar(1) archive member(object).
+ */
+struct ar_obj {
+	char	*name;		/* member name */
+	char	*buf;		/* member content */
+	void	*maddr;		/* mmap start address */
+	uid_t	 uid;		/* user id */
+	gid_t	 gid;		/* group id */
+	mode_t	 md;		/* octal file permissions */
+	size_t	 size;		/* member size */
+	time_t	 mtime;		/* modification time */
+
+	STAILQ_ENTRY(ar_obj) objs;
+};
+
+/*
+ * Structure encapsulates the "global" data for "elfcopy" program.
+ */
+struct elfcopy {
+	const char	*progname; /* program name */
+	int		 iec;	/* elfclass of input object */
+	Elftc_Bfd_Target_Flavor itf; /* flavour of input object */
+	Elftc_Bfd_Target_Flavor otf; /* flavour of output object */
+	const char	*otgt;	/* output target name */
+	int		 oec;	/* elfclass of output object */
+	unsigned char	 oed;	/* endianness of output object */
+	int		 oem;	/* EM_XXX of output object */
+	int		 abi;	/* OSABI of output object */
+	Elf		*ein;	/* ELF descriptor of input object */
+	Elf		*eout;	/* ELF descriptor of output object */
+	int		 iphnum; /* num. of input object phdr entries */
+	int		 ophnum; /* num. of output object phdr entries */
+	int		 nos;	/* num. of output object sections */
+
+	enum {
+		STRIP_NONE = 0,
+		STRIP_ALL,
+		STRIP_DEBUG,
+		STRIP_DWO,
+		STRIP_NONDEBUG,
+		STRIP_NONDWO,
+		STRIP_UNNEEDED
+	} strip;
+
+#define	EXECUTABLE	0x00000001U
+#define	DYNAMIC		0x00000002U
+#define	RELOCATABLE	0x00000004U
+#define	SYMTAB_EXIST	0x00000010U
+#define	SYMTAB_INTACT	0x00000020U
+#define	KEEP_GLOBAL	0x00000040U
+#define	DISCARD_LOCAL	0x00000080U
+#define	WEAKEN_ALL	0x00000100U
+#define	PRESERVE_DATE	0x00001000U
+#define	SREC_FORCE_S3	0x00002000U
+#define	SREC_FORCE_LEN	0x00004000U
+#define	SET_START	0x00008000U
+#define	GAP_FILL	0x00010000U
+#define	WILDCARD	0x00020000U
+#define	NO_CHANGE_WARN	0x00040000U
+#define	SEC_ADD		0x00080000U
+#define	SEC_APPEND	0x00100000U
+#define	SEC_COMPRESS	0x00200000U
+#define	SEC_PRINT	0x00400000U
+#define	SEC_REMOVE	0x00800000U
+#define	SEC_COPY	0x01000000U
+#define	DISCARD_LLABEL	0x02000000U
+#define	LOCALIZE_HIDDEN	0x04000000U
+
+	int		 flags;		/* elfcopy run control flags. */
+	int64_t		 change_addr;	/* Section address adjustment. */
+	int64_t		 change_start;	/* Entry point adjustment. */
+	uint64_t	 set_start;	/* Entry point value. */
+	unsigned long	 srec_len;	/* S-Record length. */
+	uint64_t	 pad_to;	/* load address padding. */
+	uint8_t		 fill;		/* gap fill value. */
+	char		*prefix_sec;	/* section prefix. */
+	char		*prefix_alloc;	/* alloc section prefix. */
+	char		*prefix_sym;	/* symbol prefix. */
+	char		*debuglink;	/* GNU debuglink file. */
+	struct section	*symtab;	/* .symtab section. */
+	struct section	*strtab;	/* .strtab section. */
+	struct section	*shstrtab;	/* .shstrtab section. */
+	uint64_t	*secndx;	/* section index map. */
+	uint64_t	*symndx;	/* symbol index map. */
+	unsigned char	*v_rel;		/* symbols needed by relocation. */
+	unsigned char	*v_grp;		/* symbols referred by section group. */
+	unsigned char	*v_secsym;	/* sections with section symbol. */
+	STAILQ_HEAD(, segment) v_seg;	/* list of segments. */
+	STAILQ_HEAD(, sec_action) v_sac;/* list of section operations. */
+	STAILQ_HEAD(, sec_add) v_sadd;	/* list of sections to add. */
+	STAILQ_HEAD(, symop) v_symop;	/* list of symbols operations. */
+	STAILQ_HEAD(, symfile) v_symfile; /* list of symlist files. */
+	TAILQ_HEAD(, section) v_sec;	/* list of sections. */
+
+	/*
+	 * Fields for the ar(1) archive.
+	 */
+	char		*as;		/* buffer for archive string table. */
+	size_t		 as_sz;		/* current size of as table. */
+	size_t		 as_cap;	/* capacity of as table buffer. */
+	uint32_t	 s_cnt;		/* current number of symbols. */
+	uint32_t	*s_so;		/* symbol offset table. */
+	size_t		 s_so_cap;	/* capacity of so table buffer. */
+	char		*s_sn;		/* symbol name table */
+	size_t		 s_sn_cap;	/* capacity of sn table buffer. */
+	size_t		 s_sn_sz;	/* current size of sn table. */
+	off_t		 rela_off;	/* offset relative to pseudo members. */
+	STAILQ_HEAD(, ar_obj) v_arobj;	/* archive object(member) list. */
+};
+
+void	add_section(struct elfcopy *_ecp, const char *_optarg);
+void	add_to_shstrtab(struct elfcopy *_ecp, const char *_name);
+void	add_to_symop_list(struct elfcopy *_ecp, const char *_name,
+    const char *_newname, unsigned int _op);
+void	add_to_symtab(struct elfcopy *_ecp, const char *_name,
+    uint64_t _st_value, uint64_t _st_size, uint16_t _st_shndx,
+    unsigned char _st_info, unsigned char _st_other, int _ndx_known);
+int	add_to_inseg_list(struct elfcopy *_ecp, struct section *_sec);
+void	adjust_addr(struct elfcopy *_ecp);
+void	copy_content(struct elfcopy *_ecp);
+void	copy_data(struct section *_s);
+void	copy_phdr(struct elfcopy *_ecp);
+void	copy_shdr(struct elfcopy *_ecp, struct section *_s, const char *_name,
+    int _copy, int _sec_flags);
+void	create_binary(int _ifd, int _ofd);
+void	create_elf(struct elfcopy *_ecp);
+void	create_elf_from_binary(struct elfcopy *_ecp, int _ifd, const char *ifn);
+void	create_elf_from_ihex(struct elfcopy *_ecp, int _ifd);
+void	create_elf_from_srec(struct elfcopy *_ecp, int _ifd);
+struct section *create_external_section(struct elfcopy *_ecp, const char *_name,
+    char *_newname, void *_buf, uint64_t _size, uint64_t _off, uint64_t _stype,
+    Elf_Type _dtype, uint64_t flags, uint64_t _align, uint64_t _vma,
+    int _loadable);
+void	create_external_symtab(struct elfcopy *_ecp);
+void	create_ihex(int _ifd, int _ofd);
+void	create_pe(struct elfcopy *_ecp, int _ifd, int _ofd);
+void	create_scn(struct elfcopy *_ecp);
+void	create_srec(struct elfcopy *_ecp, int _ifd, int _ofd, const char *_ofn);
+void	create_symtab(struct elfcopy *_ecp);
+void	create_symtab_data(struct elfcopy *_ecp);
+void	create_tempfile(char **_fn, int *_fd);
+void	finalize_external_symtab(struct elfcopy *_ecp);
+void	free_elf(struct elfcopy *_ecp);
+void	free_sec_act(struct elfcopy *_ecp);
+void	free_sec_add(struct elfcopy *_ecp);
+void	free_symtab(struct elfcopy *_ecp);
+void	init_shstrtab(struct elfcopy *_ecp);
+void	insert_to_sec_list(struct elfcopy *_ecp, struct section *_sec,
+    int _tail);
+struct section *insert_shtab(struct elfcopy *_ecp, int tail);
+int	is_remove_reloc_sec(struct elfcopy *_ecp, uint32_t _sh_info);
+int	is_remove_section(struct elfcopy *_ecp, const char *_name);
+struct sec_action *lookup_sec_act(struct elfcopy *_ecp,
+    const char *_name, int _add);
+struct symop *lookup_symop_list(struct elfcopy *_ecp, const char *_name,
+    unsigned int _op);
+void	resync_sections(struct elfcopy *_ecp);
+void	set_shstrtab(struct elfcopy *_ecp);
+void	setup_phdr(struct elfcopy *_ecp);
+void	update_shdr(struct elfcopy *_ecp, int _update_link);
+
+#ifndef LIBELF_AR
+int	ac_detect_ar(int _ifd);
+void	ac_create_ar(struct elfcopy *_ecp, int _ifd, int _ofd);
+#endif	/* ! LIBELF_AR */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/elfcopy/main.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,1605 @@
+/*-
+ * Copyright (c) 2007-2013 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <libelftc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "elfcopy.h"
+
+ELFTC_VCSID("$Id: main.c 3577 2017-09-14 02:19:42Z emaste $");
+
+enum options
+{
+	ECP_ADD_GNU_DEBUGLINK,
+	ECP_ADD_SECTION,
+	ECP_CHANGE_ADDR,
+	ECP_CHANGE_SEC_ADDR,
+	ECP_CHANGE_SEC_LMA,
+	ECP_CHANGE_SEC_VMA,
+	ECP_CHANGE_START,
+	ECP_CHANGE_WARN,
+	ECP_GAP_FILL,
+	ECP_GLOBALIZE_SYMBOL,
+	ECP_GLOBALIZE_SYMBOLS,
+	ECP_KEEP_SYMBOLS,
+	ECP_KEEP_GLOBAL_SYMBOLS,
+	ECP_LOCALIZE_HIDDEN,
+	ECP_LOCALIZE_SYMBOLS,
+	ECP_NO_CHANGE_WARN,
+	ECP_ONLY_DEBUG,
+	ECP_ONLY_DWO,
+	ECP_PAD_TO,
+	ECP_PREFIX_ALLOC,
+	ECP_PREFIX_SEC,
+	ECP_PREFIX_SYM,
+	ECP_REDEF_SYMBOL,
+	ECP_REDEF_SYMBOLS,
+	ECP_RENAME_SECTION,
+	ECP_SET_OSABI,
+	ECP_SET_SEC_FLAGS,
+	ECP_SET_START,
+	ECP_SREC_FORCE_S3,
+	ECP_SREC_LEN,
+	ECP_STRIP_DWO,
+	ECP_STRIP_SYMBOLS,
+	ECP_STRIP_UNNEEDED,
+	ECP_WEAKEN_ALL,
+	ECP_WEAKEN_SYMBOLS
+};
+
+static struct option mcs_longopts[] =
+{
+	{ "help", no_argument, NULL, 'h' },
+	{ "version", no_argument, NULL, 'V' },
+	{ NULL, 0, NULL, 0 }
+};
+
+static struct option strip_longopts[] =
+{
+	{"discard-all", no_argument, NULL, 'x'},
+	{"discard-locals", no_argument, NULL, 'X'},
+	{"help", no_argument, NULL, 'h'},
+	{"input-target", required_argument, NULL, 'I'},
+	{"keep-symbol", required_argument, NULL, 'K'},
+	{"only-keep-debug", no_argument, NULL, ECP_ONLY_DEBUG},
+	{"output-file", required_argument, NULL, 'o'},
+	{"output-target", required_argument, NULL, 'O'},
+	{"preserve-dates", no_argument, NULL, 'p'},
+	{"remove-section", required_argument, NULL, 'R'},
+	{"strip-all", no_argument, NULL, 's'},
+	{"strip-debug", no_argument, NULL, 'S'},
+	{"strip-symbol", required_argument, NULL, 'N'},
+	{"strip-unneeded", no_argument, NULL, ECP_STRIP_UNNEEDED},
+	{"version", no_argument, NULL, 'V'},
+	{"wildcard", no_argument, NULL, 'w'},
+	{NULL, 0, NULL, 0}
+};
+
+static struct option elfcopy_longopts[] =
+{
+	{"add-gnu-debuglink", required_argument, NULL, ECP_ADD_GNU_DEBUGLINK},
+	{"add-section", required_argument, NULL, ECP_ADD_SECTION},
+	{"adjust-section-vma", required_argument, NULL, ECP_CHANGE_SEC_ADDR},
+	{"adjust-vma", required_argument, NULL, ECP_CHANGE_ADDR},
+	{"adjust-start", required_argument, NULL, ECP_CHANGE_START},
+	{"adjust-warnings", no_argument, NULL, ECP_CHANGE_WARN},
+	{"binary-architecture", required_argument, NULL, 'B'},
+	{"change-addresses", required_argument, NULL, ECP_CHANGE_ADDR},
+	{"change-section-address", required_argument, NULL,
+	 ECP_CHANGE_SEC_ADDR},
+	{"change-section-lma", required_argument, NULL, ECP_CHANGE_SEC_LMA},
+	{"change-section-vma", required_argument, NULL, ECP_CHANGE_SEC_VMA},
+	{"change-start", required_argument, NULL, ECP_CHANGE_START},
+	{"change-warnings", no_argument, NULL, ECP_CHANGE_WARN},
+	{"discard-all", no_argument, NULL, 'x'},
+	{"discard-locals", no_argument, NULL, 'X'},
+	{"extract-dwo", no_argument, NULL, ECP_ONLY_DWO},
+	{"gap-fill", required_argument, NULL, ECP_GAP_FILL},
+	{"globalize-symbol", required_argument, NULL, ECP_GLOBALIZE_SYMBOL},
+	{"globalize-symbols", required_argument, NULL, ECP_GLOBALIZE_SYMBOLS},
+	{"help", no_argument, NULL, 'h'},
+	{"input-target", required_argument, NULL, 'I'},
+	{"keep-symbol", required_argument, NULL, 'K'},
+	{"keep-symbols", required_argument, NULL, ECP_KEEP_SYMBOLS},
+	{"keep-global-symbol", required_argument, NULL, 'G'},
+	{"keep-global-symbols", required_argument, NULL,
+	 ECP_KEEP_GLOBAL_SYMBOLS},
+	{"localize-hidden", no_argument, NULL, ECP_LOCALIZE_HIDDEN},
+	{"localize-symbol", required_argument, NULL, 'L'},
+	{"localize-symbols", required_argument, NULL, ECP_LOCALIZE_SYMBOLS},
+	{"no-adjust-warnings", no_argument, NULL, ECP_NO_CHANGE_WARN},
+	{"no-change-warnings", no_argument, NULL, ECP_NO_CHANGE_WARN},
+	{"only-keep-debug", no_argument, NULL, ECP_ONLY_DEBUG},
+	{"only-section", required_argument, NULL, 'j'},
+	{"osabi", required_argument, NULL, ECP_SET_OSABI},
+	{"output-target", required_argument, NULL, 'O'},
+	{"pad-to", required_argument, NULL, ECP_PAD_TO},
+	{"preserve-dates", no_argument, NULL, 'p'},
+	{"prefix-alloc-sections", required_argument, NULL, ECP_PREFIX_ALLOC},
+	{"prefix-sections", required_argument, NULL, ECP_PREFIX_SEC},
+	{"prefix-symbols", required_argument, NULL, ECP_PREFIX_SYM},
+	{"redefine-sym", required_argument, NULL, ECP_REDEF_SYMBOL},
+	{"redefine-syms", required_argument, NULL, ECP_REDEF_SYMBOLS},
+	{"remove-section", required_argument, NULL, 'R'},
+	{"rename-section", required_argument, NULL, ECP_RENAME_SECTION},
+	{"set-section-flags", required_argument, NULL, ECP_SET_SEC_FLAGS},
+	{"set-start", required_argument, NULL, ECP_SET_START},
+	{"srec-forceS3", no_argument, NULL, ECP_SREC_FORCE_S3},
+	{"srec-len", required_argument, NULL, ECP_SREC_LEN},
+	{"strip-all", no_argument, NULL, 'S'},
+	{"strip-debug", no_argument, 0, 'g'},
+	{"strip-dwo", no_argument, NULL, ECP_STRIP_DWO},
+	{"strip-symbol", required_argument, NULL, 'N'},
+	{"strip-symbols", required_argument, NULL, ECP_STRIP_SYMBOLS},
+	{"strip-unneeded", no_argument, NULL, ECP_STRIP_UNNEEDED},
+	{"version", no_argument, NULL, 'V'},
+	{"weaken", no_argument, NULL, ECP_WEAKEN_ALL},
+	{"weaken-symbol", required_argument, NULL, 'W'},
+	{"weaken-symbols", required_argument, NULL, ECP_WEAKEN_SYMBOLS},
+	{"wildcard", no_argument, NULL, 'w'},
+	{NULL, 0, NULL, 0}
+};
+
+static struct {
+	const char *name;
+	int value;
+} sec_flags[] = {
+	{"alloc", SF_ALLOC},
+	{"load", SF_LOAD},
+	{"noload", SF_NOLOAD},
+	{"readonly", SF_READONLY},
+	{"debug", SF_DEBUG},
+	{"code", SF_CODE},
+	{"data", SF_DATA},
+	{"rom", SF_ROM},
+	{"share", SF_SHARED},
+	{"contents", SF_CONTENTS},
+	{NULL, 0}
+};
+
+static struct {
+	const char *name;
+	int abi;
+} osabis[] = {
+	{"sysv", ELFOSABI_SYSV},
+	{"hpus", ELFOSABI_HPUX},
+	{"netbsd", ELFOSABI_NETBSD},
+	{"linux", ELFOSABI_LINUX},
+	{"hurd", ELFOSABI_HURD},
+	{"86open", ELFOSABI_86OPEN},
+	{"solaris", ELFOSABI_SOLARIS},
+	{"aix", ELFOSABI_AIX},
+	{"irix", ELFOSABI_IRIX},
+	{"freebsd", ELFOSABI_FREEBSD},
+	{"tru64", ELFOSABI_TRU64},
+	{"modesto", ELFOSABI_MODESTO},
+	{"openbsd", ELFOSABI_OPENBSD},
+	{"openvms", ELFOSABI_OPENVMS},
+	{"nsk", ELFOSABI_NSK},
+	{"cloudabi", ELFOSABI_CLOUDABI},
+	{"arm", ELFOSABI_ARM},
+	{"standalone", ELFOSABI_STANDALONE},
+	{NULL, 0}
+};
+
+static int	copy_from_tempfile(const char *src, const char *dst,
+    int infd, int *outfd, int in_place);
+static void	create_file(struct elfcopy *ecp, const char *src,
+    const char *dst);
+static void	elfcopy_main(struct elfcopy *ecp, int argc, char **argv);
+static void	elfcopy_usage(void);
+static void	mcs_main(struct elfcopy *ecp, int argc, char **argv);
+static void	mcs_usage(void);
+static void	parse_sec_address_op(struct elfcopy *ecp, int optnum,
+    const char *optname, char *s);
+static void	parse_sec_flags(struct sec_action *sac, char *s);
+static void	parse_symlist_file(struct elfcopy *ecp, const char *fn,
+    unsigned int op);
+static void	print_version(void);
+static void	set_input_target(struct elfcopy *ecp, const char *target_name);
+static void	set_osabi(struct elfcopy *ecp, const char *abi);
+static void	set_output_target(struct elfcopy *ecp, const char *target_name);
+static void	strip_main(struct elfcopy *ecp, int argc, char **argv);
+static void	strip_usage(void);
+
+/*
+ * An ELF object usually has a structure described by the
+ * diagram below.
+ *  _____________
+ * |             |
+ * |     NULL    | <- always a SHT_NULL section
+ * |_____________|
+ * |             |
+ * |   .interp   |
+ * |_____________|
+ * |             |
+ * |     ...     |
+ * |_____________|
+ * |             |
+ * |    .text    |
+ * |_____________|
+ * |             |
+ * |     ...     |
+ * |_____________|
+ * |             |
+ * |  .comment   | <- above(include) this: normal sections
+ * |_____________|
+ * |             |
+ * | add sections| <- unloadable sections added by --add-section
+ * |_____________|
+ * |             |
+ * |  .shstrtab  | <- section name string table
+ * |_____________|
+ * |             |
+ * |    shdrs    | <- section header table
+ * |_____________|
+ * |             |
+ * |   .symtab   | <- symbol table, if any
+ * |_____________|
+ * |             |
+ * |   .strtab   | <- symbol name string table, if any
+ * |_____________|
+ * |             |
+ * |  .rel.text  | <- relocation info for .o files.
+ * |_____________|
+ */
+void
+create_elf(struct elfcopy *ecp)
+{
+	struct section	*shtab;
+	GElf_Ehdr	 ieh;
+	GElf_Ehdr	 oeh;
+	size_t		 ishnum;
+
+	ecp->flags |= SYMTAB_INTACT;
+	ecp->flags &= ~SYMTAB_EXIST;
+
+	/* Create EHDR. */
+	if (gelf_getehdr(ecp->ein, &ieh) == NULL)
+		errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
+		    elf_errmsg(-1));
+	if ((ecp->iec = gelf_getclass(ecp->ein)) == ELFCLASSNONE)
+		errx(EXIT_FAILURE, "getclass() failed: %s",
+		    elf_errmsg(-1));
+
+	if (ecp->oec == ELFCLASSNONE)
+		ecp->oec = ecp->iec;
+	if (ecp->oed == ELFDATANONE)
+		ecp->oed = ieh.e_ident[EI_DATA];
+
+	if (gelf_newehdr(ecp->eout, ecp->oec) == NULL)
+		errx(EXIT_FAILURE, "gelf_newehdr failed: %s",
+		    elf_errmsg(-1));
+	if (gelf_getehdr(ecp->eout, &oeh) == NULL)
+		errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
+		    elf_errmsg(-1));
+
+	memcpy(oeh.e_ident, ieh.e_ident, sizeof(ieh.e_ident));
+	oeh.e_ident[EI_CLASS] = ecp->oec;
+	oeh.e_ident[EI_DATA]  = ecp->oed;
+	if (ecp->abi != -1)
+		oeh.e_ident[EI_OSABI] = ecp->abi;
+	oeh.e_flags	      = ieh.e_flags;
+	oeh.e_machine	      = ieh.e_machine;
+	oeh.e_type	      = ieh.e_type;
+	oeh.e_entry	      = ieh.e_entry;
+	oeh.e_version	      = ieh.e_version;
+
+	ecp->flags &= ~(EXECUTABLE | DYNAMIC | RELOCATABLE);
+	if (ieh.e_type == ET_EXEC)
+		ecp->flags |= EXECUTABLE;
+	else if (ieh.e_type == ET_DYN)
+		ecp->flags |= DYNAMIC;
+	else if (ieh.e_type == ET_REL)
+		ecp->flags |= RELOCATABLE;
+	else
+		errx(EXIT_FAILURE, "unsupported e_type");
+
+	if (!elf_getshnum(ecp->ein, &ishnum))
+		errx(EXIT_FAILURE, "elf_getshnum failed: %s",
+		    elf_errmsg(-1));
+	if (ishnum > 0 && (ecp->secndx = calloc(ishnum,
+	    sizeof(*ecp->secndx))) == NULL)
+		err(EXIT_FAILURE, "calloc failed");
+
+	/* Read input object program header. */
+	setup_phdr(ecp);
+
+	/*
+	 * Scan of input sections: we iterate through sections from input
+	 * object, skip sections need to be stripped, allot Elf_Scn and
+	 * create internal section structure for sections we want.
+	 * (i.e., determine output sections)
+	 */
+	create_scn(ecp);
+
+	/* Apply section address changes, if any. */
+	adjust_addr(ecp);
+
+	/*
+	 * Determine if the symbol table needs to be changed based on
+	 * command line options.
+	 */
+	if (ecp->strip == STRIP_DEBUG ||
+	    ecp->strip == STRIP_UNNEEDED ||
+	    ecp->flags & WEAKEN_ALL ||
+	    ecp->flags & LOCALIZE_HIDDEN ||
+	    ecp->flags & DISCARD_LOCAL ||
+	    ecp->flags & DISCARD_LLABEL ||
+	    ecp->prefix_sym != NULL ||
+	    !STAILQ_EMPTY(&ecp->v_symop))
+		ecp->flags &= ~SYMTAB_INTACT;
+
+	/*
+	 * Create symbol table. Symbols are filtered or stripped according to
+	 * command line args specified by user, and later updated for the new
+	 * layout of sections in the output object.
+	 */
+	if ((ecp->flags & SYMTAB_EXIST) != 0)
+		create_symtab(ecp);
+
+	/*
+	 * Write the underlying ehdr. Note that it should be called
+	 * before elf_setshstrndx() since it will overwrite e->e_shstrndx.
+	 */
+	if (gelf_update_ehdr(ecp->eout, &oeh) == 0)
+		errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s",
+		    elf_errmsg(-1));
+
+	/*
+	 * First processing of output sections: at this stage we copy the
+	 * content of each section from input to output object.  Section
+	 * content will be modified and printed (mcs) if need. Also content of
+	 * relocation section probably will be filtered and updated according
+	 * to symbol table changes.
+	 */
+	copy_content(ecp);
+
+	/* Generate section name string table (.shstrtab). */
+	set_shstrtab(ecp);
+
+	/*
+	 * Second processing of output sections: Update section headers.
+	 * At this stage we set name string index, update st_link and st_info
+	 * for output sections.
+	 */
+	update_shdr(ecp, 1);
+
+	/* Renew oeh to get the updated e_shstrndx. */
+	if (gelf_getehdr(ecp->eout, &oeh) == NULL)
+		errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
+		    elf_errmsg(-1));
+
+	/*
+	 * Insert SHDR table into the internal section list as a "pseudo"
+	 * section, so later it will get sorted and resynced just as "normal"
+	 * sections.
+	 *
+	 * Under FreeBSD, Binutils objcopy always put the section header
+	 * at the end of all the sections. We want to do the same here.
+	 *
+	 * However, note that the behaviour is still different with Binutils:
+	 * elfcopy checks the FreeBSD OSABI tag to tell whether it needs to
+	 * move the section headers, while Binutils is probably configured
+	 * this way when it's compiled on FreeBSD.
+	 */
+	if (oeh.e_ident[EI_OSABI] == ELFOSABI_FREEBSD)
+		shtab = insert_shtab(ecp, 1);
+	else
+		shtab = insert_shtab(ecp, 0);
+
+	/*
+	 * Resync section offsets in the output object. This is needed
+	 * because probably sections are modified or new sections are added,
+	 * as a result overlap/gap might appears.
+	 */
+	resync_sections(ecp);
+
+	/* Store SHDR offset in EHDR. */
+	oeh.e_shoff = shtab->off;
+
+	/* Put program header table immediately after the Elf header. */
+	if (ecp->ophnum > 0) {
+		oeh.e_phoff = gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT);
+		if (oeh.e_phoff == 0)
+			errx(EXIT_FAILURE, "gelf_fsize() failed: %s",
+			    elf_errmsg(-1));
+	}
+
+	/*
+	 * Update ELF object entry point if requested.
+	 */
+	if (ecp->change_addr != 0)
+		oeh.e_entry += ecp->change_addr;
+	if (ecp->flags & SET_START)
+		oeh.e_entry = ecp->set_start;
+	if (ecp->change_start != 0)
+		oeh.e_entry += ecp->change_start;
+
+	/*
+	 * Update ehdr again before we call elf_update(), since we
+	 * modified e_shoff and e_phoff.
+	 */
+	if (gelf_update_ehdr(ecp->eout, &oeh) == 0)
+		errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s",
+		    elf_errmsg(-1));
+
+	if (ecp->ophnum > 0)
+		copy_phdr(ecp);
+
+	/* Write out the output elf object. */
+	if (elf_update(ecp->eout, ELF_C_WRITE) < 0)
+		errx(EXIT_FAILURE, "elf_update() failed: %s",
+		    elf_errmsg(-1));
+
+	/* Release allocated resource. */
+	free_elf(ecp);
+}
+
+void
+free_elf(struct elfcopy *ecp)
+{
+	struct segment	*seg, *seg_temp;
+	struct section	*sec, *sec_temp;
+
+	/* Free internal segment list. */
+	if (!STAILQ_EMPTY(&ecp->v_seg)) {
+		STAILQ_FOREACH_SAFE(seg, &ecp->v_seg, seg_list, seg_temp) {
+			STAILQ_REMOVE(&ecp->v_seg, seg, segment, seg_list);
+			free(seg);
+		}
+	}
+
+	/* Free symbol table buffers. */
+	free_symtab(ecp);
+
+	/* Free internal section list. */
+	if (!TAILQ_EMPTY(&ecp->v_sec)) {
+		TAILQ_FOREACH_SAFE(sec, &ecp->v_sec, sec_list, sec_temp) {
+			TAILQ_REMOVE(&ecp->v_sec, sec, sec_list);
+			if (sec->buf != NULL)
+				free(sec->buf);
+			if (sec->newname != NULL)
+				free(sec->newname);
+			if (sec->pad != NULL)
+				free(sec->pad);
+			free(sec);
+		}
+	}
+
+	ecp->symtab = NULL;
+	ecp->strtab = NULL;
+	ecp->shstrtab = NULL;
+
+	if (ecp->secndx != NULL) {
+		free(ecp->secndx);
+		ecp->secndx = NULL;
+	}
+}
+
+/* Create a temporary file. */
+void
+create_tempfile(char **fn, int *fd)
+{
+	const char	*tmpdir;
+	char		*cp, *tmpf;
+	size_t		 tlen, plen;
+
+#define	_TEMPFILE "ecp.XXXXXXXX"
+#define	_TEMPFILEPATH "/tmp/ecp.XXXXXXXX"
+
+	if (fn == NULL || fd == NULL)
+		return;
+	/* Repect TMPDIR environment variable. */
+	tmpdir = getenv("TMPDIR");
+	if (tmpdir != NULL && *tmpdir != '\0') {
+		tlen = strlen(tmpdir);
+		plen = strlen(_TEMPFILE);
+		tmpf = malloc(tlen + plen + 2);
+		if (tmpf == NULL)
+			err(EXIT_FAILURE, "malloc failed");
+		strncpy(tmpf, tmpdir, tlen);
+		cp = &tmpf[tlen - 1];
+		if (*cp++ != '/')
+			*cp++ = '/';
+		strncpy(cp, _TEMPFILE, plen);
+		cp[plen] = '\0';
+	} else {
+		tmpf = strdup(_TEMPFILEPATH);
+		if (tmpf == NULL)
+			err(EXIT_FAILURE, "strdup failed");
+	}
+	if ((*fd = mkstemp(tmpf)) == -1)
+		err(EXIT_FAILURE, "mkstemp %s failed", tmpf);
+	if (fchmod(*fd, 0644) == -1)
+		err(EXIT_FAILURE, "fchmod %s failed", tmpf);
+	*fn = tmpf;
+
+#undef _TEMPFILE
+#undef _TEMPFILEPATH
+}
+
+/*
+ * Copy temporary file with path src and file descriptor infd to path dst.
+ * If in_place is set act as if editing the file in place, avoiding rename()
+ * to preserve hard and symbolic links. Output file remains open, with file
+ * descriptor returned in outfd.
+ */
+static int
+copy_from_tempfile(const char *src, const char *dst, int infd, int *outfd,
+    int in_place)
+{
+	int tmpfd;
+
+	/*
+	 * First, check if we can use rename().
+	 */
+	if (in_place == 0) {
+		if (rename(src, dst) >= 0) {
+			*outfd = infd;
+			return (0);
+		} else if (errno != EXDEV)
+			return (-1);
+	
+		/*
+		 * If the rename() failed due to 'src' and 'dst' residing in
+		 * two different file systems, invoke a helper function in
+		 * libelftc to do the copy.
+		 */
+
+		if (unlink(dst) < 0)
+			return (-1);
+	}
+
+	if ((tmpfd = open(dst, O_CREAT | O_TRUNC | O_WRONLY, 0755)) < 0)
+		return (-1);
+
+	if (elftc_copyfile(infd, tmpfd) < 0)
+		return (-1);
+
+	/*
+	 * Remove the temporary file from the file system
+	 * namespace, and close its file descriptor.
+	 */
+	if (unlink(src) < 0)
+		return (-1);
+
+	(void) close(infd);
+
+	/*
+	 * Return the file descriptor for the destination.
+	 */
+	*outfd = tmpfd;
+
+	return (0);
+}
+
+static void
+create_file(struct elfcopy *ecp, const char *src, const char *dst)
+{
+	struct stat	 sb;
+	char		*tempfile, *elftemp;
+	int		 efd, ifd, ofd, ofd0, tfd;
+	int		 in_place;
+
+	tempfile = NULL;
+
+	if (src == NULL)
+		errx(EXIT_FAILURE, "internal: src == NULL");
+	if ((ifd = open(src, O_RDONLY)) == -1)
+		err(EXIT_FAILURE, "open %s failed", src);
+
+	if (fstat(ifd, &sb) == -1)
+		err(EXIT_FAILURE, "fstat %s failed", src);
+
+	if (dst == NULL)
+		create_tempfile(&tempfile, &ofd);
+	else
+		if ((ofd = open(dst, O_RDWR|O_CREAT, 0755)) == -1)
+			err(EXIT_FAILURE, "open %s failed", dst);
+
+#ifndef LIBELF_AR
+	/* Detect and process ar(1) archive using libarchive. */
+	if (ac_detect_ar(ifd)) {
+		ac_create_ar(ecp, ifd, ofd);
+		goto copy_done;
+	}
+#endif
+
+	if (lseek(ifd, 0, SEEK_SET) < 0)
+		err(EXIT_FAILURE, "lseek failed");
+
+	/*
+	 * If input object is not ELF file, convert it to an intermediate
+	 * ELF object before processing.
+	 */
+	if (ecp->itf != ETF_ELF) {
+		/*
+		 * If the output object is not an ELF file, choose an arbitrary
+		 * ELF format for the intermediate file. srec, ihex and binary
+		 * formats are independent of class, endianness and machine
+		 * type so these choices do not affect the output.
+		 */
+		if (ecp->otf != ETF_ELF) {
+			if (ecp->oec == ELFCLASSNONE)
+				ecp->oec = ELFCLASS64;
+			if (ecp->oed == ELFDATANONE)
+				ecp->oed = ELFDATA2LSB;
+		}
+		create_tempfile(&elftemp, &efd);
+		if ((ecp->eout = elf_begin(efd, ELF_C_WRITE, NULL)) == NULL)
+			errx(EXIT_FAILURE, "elf_begin() failed: %s",
+			    elf_errmsg(-1));
+		elf_flagelf(ecp->eout, ELF_C_SET, ELF_F_LAYOUT);
+		if (ecp->itf == ETF_BINARY)
+			create_elf_from_binary(ecp, ifd, src);
+		else if (ecp->itf == ETF_IHEX)
+			create_elf_from_ihex(ecp, ifd);
+		else if (ecp->itf == ETF_SREC)
+			create_elf_from_srec(ecp, ifd);
+		else
+			errx(EXIT_FAILURE, "Internal: invalid target flavour");
+		elf_end(ecp->eout);
+
+		/* Open intermediate ELF object as new input object. */
+		close(ifd);
+		if ((ifd = open(elftemp, O_RDONLY)) == -1)
+			err(EXIT_FAILURE, "open %s failed", src);
+		close(efd);
+		if (unlink(elftemp) < 0)
+			err(EXIT_FAILURE, "unlink %s failed", elftemp);
+		free(elftemp);
+	}
+
+	if ((ecp->ein = elf_begin(ifd, ELF_C_READ, NULL)) == NULL)
+		errx(EXIT_FAILURE, "elf_begin() failed: %s",
+		    elf_errmsg(-1));
+
+	switch (elf_kind(ecp->ein)) {
+	case ELF_K_NONE:
+		errx(EXIT_FAILURE, "file format not recognized");
+	case ELF_K_ELF:
+		if ((ecp->eout = elf_begin(ofd, ELF_C_WRITE, NULL)) == NULL)
+			errx(EXIT_FAILURE, "elf_begin() failed: %s",
+			    elf_errmsg(-1));
+
+		/* elfcopy(1) manage ELF layout by itself. */
+		elf_flagelf(ecp->eout, ELF_C_SET, ELF_F_LAYOUT);
+
+		/*
+		 * Create output ELF object.
+		 */
+		create_elf(ecp);
+		elf_end(ecp->eout);
+
+		/*
+		 * Convert the output ELF object to binary/srec/ihex if need.
+		 */
+		if (ecp->otf != ETF_ELF) {
+			/*
+			 * Create (another) tempfile for binary/srec/ihex
+			 * output object.
+			 */
+			if (tempfile != NULL) {
+				if (unlink(tempfile) < 0)
+					err(EXIT_FAILURE, "unlink %s failed",
+					    tempfile);
+				free(tempfile);
+			}
+			create_tempfile(&tempfile, &ofd0);
+
+
+			/*
+			 * Rewind the file descriptor being processed.
+			 */
+			if (lseek(ofd, 0, SEEK_SET) < 0)
+				err(EXIT_FAILURE,
+				    "lseek failed for the output object");
+
+			/*
+			 * Call flavour-specific conversion routine.
+			 */
+			switch (ecp->otf) {
+			case ETF_BINARY:
+				create_binary(ofd, ofd0);
+				break;
+			case ETF_IHEX:
+				create_ihex(ofd, ofd0);
+				break;
+			case ETF_SREC:
+				create_srec(ecp, ofd, ofd0,
+				    dst != NULL ? dst : src);
+				break;
+			case ETF_PE:
+			case ETF_EFI:
+#if	WITH_PE
+				create_pe(ecp, ofd, ofd0);
+#else
+				errx(EXIT_FAILURE, "PE/EFI support not enabled"
+				    " at compile time");
+#endif
+				break;
+			default:
+				errx(EXIT_FAILURE, "Internal: unsupported"
+				    " output flavour %d", ecp->oec);
+			}
+
+			close(ofd);
+			ofd = ofd0;
+		}
+
+		break;
+
+	case ELF_K_AR:
+		/* XXX: Not yet supported. */
+		break;
+	default:
+		errx(EXIT_FAILURE, "file format not supported");
+	}
+
+	elf_end(ecp->ein);
+
+#ifndef LIBELF_AR
+copy_done:
+#endif
+
+	if (tempfile != NULL) {
+		in_place = 0;
+		if (dst == NULL) {
+			dst = src;
+			if (lstat(dst, &sb) != -1 &&
+			    (sb.st_nlink > 1 || S_ISLNK(sb.st_mode)))
+				in_place = 1;
+		}
+
+		if (copy_from_tempfile(tempfile, dst, ofd, &tfd, in_place) < 0)
+			err(EXIT_FAILURE, "creation of %s failed", dst);
+
+		free(tempfile);
+		tempfile = NULL;
+
+		ofd = tfd;
+	}
+
+	if (strcmp(dst, "/dev/null") && fchmod(ofd, sb.st_mode) == -1)
+		err(EXIT_FAILURE, "fchmod %s failed", dst);
+
+	if ((ecp->flags & PRESERVE_DATE) &&
+	    elftc_set_timestamps(dst, &sb) < 0)
+		err(EXIT_FAILURE, "setting timestamps failed");
+
+	close(ifd);
+	close(ofd);
+}
+
+static void
+elfcopy_main(struct elfcopy *ecp, int argc, char **argv)
+{
+	struct sec_action	*sac;
+	const char		*infile, *outfile;
+	char			*fn, *s;
+	int			 opt;
+
+	while ((opt = getopt_long(argc, argv, "dB:gG:I:j:K:L:N:O:pR:s:SwW:xXV",
+	    elfcopy_longopts, NULL)) != -1) {
+		switch(opt) {
+		case 'B':
+			/* ignored */
+			break;
+		case 'R':
+			sac = lookup_sec_act(ecp, optarg, 1);
+			if (sac->copy != 0)
+				errx(EXIT_FAILURE,
+				    "both copy and remove specified");
+			sac->remove = 1;
+			ecp->flags |= SEC_REMOVE;
+			break;
+		case 'S':
+			ecp->strip = STRIP_ALL;
+			break;
+		case 'g':
+			ecp->strip = STRIP_DEBUG;
+			break;
+		case 'G':
+			ecp->flags |= KEEP_GLOBAL;
+			add_to_symop_list(ecp, optarg, NULL, SYMOP_KEEPG);
+			break;
+		case 'I':
+		case 's':
+			set_input_target(ecp, optarg);
+			break;
+		case 'j':
+			sac = lookup_sec_act(ecp, optarg, 1);
+			if (sac->remove != 0)
+				errx(EXIT_FAILURE,
+				    "both copy and remove specified");
+			sac->copy = 1;
+			ecp->flags |= SEC_COPY;
+			break;
+		case 'K':
+			add_to_symop_list(ecp, optarg, NULL, SYMOP_KEEP);
+			break;
+		case 'L':
+			add_to_symop_list(ecp, optarg, NULL, SYMOP_LOCALIZE);
+			break;
+		case 'N':
+			add_to_symop_list(ecp, optarg, NULL, SYMOP_STRIP);
+			break;
+		case 'O':
+			set_output_target(ecp, optarg);
+			break;
+		case 'p':
+			ecp->flags |= PRESERVE_DATE;
+			break;
+		case 'V':
+			print_version();
+			break;
+		case 'w':
+			ecp->flags |= WILDCARD;
+			break;
+		case 'W':
+			add_to_symop_list(ecp, optarg, NULL, SYMOP_WEAKEN);
+			break;
+		case 'x':
+			ecp->flags |= DISCARD_LOCAL;
+			break;
+		case 'X':
+			ecp->flags |= DISCARD_LLABEL;
+			break;
+		case ECP_ADD_GNU_DEBUGLINK:
+			ecp->debuglink = optarg;
+			break;
+		case ECP_ADD_SECTION:
+			add_section(ecp, optarg);
+			break;
+		case ECP_CHANGE_ADDR:
+			ecp->change_addr = (int64_t) strtoll(optarg, NULL, 0);
+			break;
+		case ECP_CHANGE_SEC_ADDR:
+			parse_sec_address_op(ecp, opt, "--change-section-addr",
+			    optarg);
+			break;
+		case ECP_CHANGE_SEC_LMA:
+			parse_sec_address_op(ecp, opt, "--change-section-lma",
+			    optarg);
+			break;
+		case ECP_CHANGE_SEC_VMA:
+			parse_sec_address_op(ecp, opt, "--change-section-vma",
+			    optarg);
+			break;
+		case ECP_CHANGE_START:
+			ecp->change_start = (int64_t) strtoll(optarg, NULL, 0);
+			break;
+		case ECP_CHANGE_WARN:
+			/* default */
+			break;
+		case ECP_GAP_FILL:
+			ecp->fill = (uint8_t) strtoul(optarg, NULL, 0);
+			ecp->flags |= GAP_FILL;
+			break;
+		case ECP_GLOBALIZE_SYMBOL:
+			add_to_symop_list(ecp, optarg, NULL, SYMOP_GLOBALIZE);
+			break;
+		case ECP_GLOBALIZE_SYMBOLS:
+			parse_symlist_file(ecp, optarg, SYMOP_GLOBALIZE);
+			break;
+		case ECP_KEEP_SYMBOLS:
+			parse_symlist_file(ecp, optarg, SYMOP_KEEP);
+			break;
+		case ECP_KEEP_GLOBAL_SYMBOLS:
+			parse_symlist_file(ecp, optarg, SYMOP_KEEPG);
+			break;
+		case ECP_LOCALIZE_HIDDEN:
+			ecp->flags |= LOCALIZE_HIDDEN;
+			break;
+		case ECP_LOCALIZE_SYMBOLS:
+			parse_symlist_file(ecp, optarg, SYMOP_LOCALIZE);
+			break;
+		case ECP_NO_CHANGE_WARN:
+			ecp->flags |= NO_CHANGE_WARN;
+			break;
+		case ECP_ONLY_DEBUG:
+			ecp->strip = STRIP_NONDEBUG;
+			break;
+		case ECP_ONLY_DWO:
+			ecp->strip = STRIP_NONDWO;
+			break;
+		case ECP_PAD_TO:
+			ecp->pad_to = (uint64_t) strtoull(optarg, NULL, 0);
+			break;
+		case ECP_PREFIX_ALLOC:
+			ecp->prefix_alloc = optarg;
+			break;
+		case ECP_PREFIX_SEC:
+			ecp->prefix_sec = optarg;
+			break;
+		case ECP_PREFIX_SYM:
+			ecp->prefix_sym = optarg;
+			break;
+		case ECP_REDEF_SYMBOL:
+			if ((s = strchr(optarg, '=')) == NULL)
+				errx(EXIT_FAILURE,
+				    "illegal format for --redefine-sym");
+			*s++ = '\0';
+			add_to_symop_list(ecp, optarg, s, SYMOP_REDEF);
+			break;
+		case ECP_REDEF_SYMBOLS:
+			parse_symlist_file(ecp, optarg, SYMOP_REDEF);
+			break;
+		case ECP_RENAME_SECTION:
+			if ((fn = strchr(optarg, '=')) == NULL)
+				errx(EXIT_FAILURE,
+				    "illegal format for --rename-section");
+			*fn++ = '\0';
+
+			/* Check for optional flags. */
+			if ((s = strchr(fn, ',')) != NULL)
+				*s++ = '\0';
+
+			sac = lookup_sec_act(ecp, optarg, 1);
+			sac->rename = 1;
+			sac->newname = fn;
+			if (s != NULL)
+				parse_sec_flags(sac, s);
+			break;
+		case ECP_SET_OSABI:
+			set_osabi(ecp, optarg);
+			break;
+		case ECP_SET_SEC_FLAGS:
+			if ((s = strchr(optarg, '=')) == NULL)
+				errx(EXIT_FAILURE,
+				    "illegal format for --set-section-flags");
+			*s++ = '\0';
+			sac = lookup_sec_act(ecp, optarg, 1);
+			parse_sec_flags(sac, s);
+			break;
+		case ECP_SET_START:
+			ecp->flags |= SET_START;
+			ecp->set_start = (uint64_t) strtoull(optarg, NULL, 0);
+			break;
+		case ECP_SREC_FORCE_S3:
+			ecp->flags |= SREC_FORCE_S3;
+			break;
+		case ECP_SREC_LEN:
+			ecp->flags |= SREC_FORCE_LEN;
+			ecp->srec_len = strtoul(optarg, NULL, 0);
+			break;
+		case ECP_STRIP_DWO:
+			ecp->strip = STRIP_DWO;
+			break;
+		case ECP_STRIP_SYMBOLS:
+			parse_symlist_file(ecp, optarg, SYMOP_STRIP);
+			break;
+		case ECP_STRIP_UNNEEDED:
+			ecp->strip = STRIP_UNNEEDED;
+			break;
+		case ECP_WEAKEN_ALL:
+			ecp->flags |= WEAKEN_ALL;
+			break;
+		case ECP_WEAKEN_SYMBOLS:
+			parse_symlist_file(ecp, optarg, SYMOP_WEAKEN);
+			break;
+		default:
+			elfcopy_usage();
+		}
+	}
+
+	if (optind == argc || optind + 2 < argc)
+		elfcopy_usage();
+
+	infile = argv[optind];
+	outfile = NULL;
+	if (optind + 1 < argc)
+		outfile = argv[optind + 1];
+
+	create_file(ecp, infile, outfile);
+}
+
+static void
+mcs_main(struct elfcopy *ecp, int argc, char **argv)
+{
+	struct sec_action	*sac;
+	const char		*string;
+	int			 append, delete, compress, name, print;
+	int			 opt, i;
+
+	append = delete = compress = name = print = 0;
+	string = NULL;
+	while ((opt = getopt_long(argc, argv, "a:cdhn:pV", mcs_longopts,
+		NULL)) != -1) {
+		switch(opt) {
+		case 'a':
+			append = 1;
+			string = optarg; /* XXX multiple -a not supported */
+			break;
+		case 'c':
+			compress = 1;
+			break;
+		case 'd':
+			delete = 1;
+			break;
+		case 'n':
+			name = 1;
+			(void)lookup_sec_act(ecp, optarg, 1);
+			break;
+		case 'p':
+			print = 1;
+			break;
+		case 'V':
+			print_version();
+			break;
+		case 'h':
+		default:
+			mcs_usage();
+		}
+	}
+
+	if (optind == argc)
+		mcs_usage();
+
+	/* Must specify one operation at least. */
+	if (!append && !compress && !delete && !print)
+		mcs_usage();
+
+	/*
+	 * If we are going to delete, ignore other operations. This is
+	 * different from the Solaris implementation, which can print
+	 * and delete a section at the same time, for example. Also, this
+	 * implementation do not respect the order between operations that
+	 * user specified, i.e., "mcs -pc a.out" equals to "mcs -cp a.out".
+	 */
+	if (delete) {
+		append = compress = print = 0;
+		ecp->flags |= SEC_REMOVE;
+	}
+	if (append)
+		ecp->flags |= SEC_APPEND;
+	if (compress)
+		ecp->flags |= SEC_COMPRESS;
+	if (print)
+		ecp->flags |= SEC_PRINT;
+
+	/* .comment is the default section to operate on. */
+	if (!name)
+		(void)lookup_sec_act(ecp, ".comment", 1);
+
+	STAILQ_FOREACH(sac, &ecp->v_sac, sac_list) {
+		sac->append = append;
+		sac->compress = compress;
+		sac->print = print;
+		sac->remove = delete;
+		sac->string = string;
+	}
+
+	for (i = optind; i < argc; i++) {
+		/* If only -p is specified, output to /dev/null */
+		if (print && !append && !compress && !delete)
+			create_file(ecp, argv[i], "/dev/null");
+		else
+			create_file(ecp, argv[i], NULL);
+	}
+}
+
+static void
+strip_main(struct elfcopy *ecp, int argc, char **argv)
+{
+	struct sec_action	*sac;
+	const char		*outfile;
+	int			 opt;
+	int			 i;
+
+	outfile = NULL;
+	while ((opt = getopt_long(argc, argv, "hI:K:N:o:O:pR:sSdgVxXw",
+	    strip_longopts, NULL)) != -1) {
+		switch(opt) {
+		case 'R':
+			sac = lookup_sec_act(ecp, optarg, 1);
+			sac->remove = 1;
+			ecp->flags |= SEC_REMOVE;
+			break;
+		case 's':
+			ecp->strip = STRIP_ALL;
+			break;
+		case 'S':
+		case 'g':
+		case 'd':
+			ecp->strip = STRIP_DEBUG;
+			break;
+		case 'I':
+			/* ignored */
+			break;
+		case 'K':
+			add_to_symop_list(ecp, optarg, NULL, SYMOP_KEEP);
+			break;
+		case 'N':
+			add_to_symop_list(ecp, optarg, NULL, SYMOP_STRIP);
+			break;
+		case 'o':
+			outfile = optarg;
+			break;
+		case 'O':
+			set_output_target(ecp, optarg);
+			break;
+		case 'p':
+			ecp->flags |= PRESERVE_DATE;
+			break;
+		case 'V':
+			print_version();
+			break;
+		case 'w':
+			ecp->flags |= WILDCARD;
+			break;
+		case 'x':
+			ecp->flags |= DISCARD_LOCAL;
+			break;
+		case 'X':
+			ecp->flags |= DISCARD_LLABEL;
+			break;
+		case ECP_ONLY_DEBUG:
+			ecp->strip = STRIP_NONDEBUG;
+			break;
+		case ECP_STRIP_UNNEEDED:
+			ecp->strip = STRIP_UNNEEDED;
+			break;
+		case 'h':
+		default:
+			strip_usage();
+		}
+	}
+
+	if (ecp->strip == 0 &&
+	    ((ecp->flags & DISCARD_LOCAL) == 0) &&
+	    ((ecp->flags & DISCARD_LLABEL) == 0) &&
+	    lookup_symop_list(ecp, NULL, SYMOP_STRIP) == NULL)
+		ecp->strip = STRIP_ALL;
+	if (optind == argc)
+		strip_usage();
+
+	for (i = optind; i < argc; i++)
+		create_file(ecp, argv[i], outfile);
+}
+
+static void
+parse_sec_flags(struct sec_action *sac, char *s)
+{
+	const char	*flag;
+	int		 found, i;
+
+	for (flag = strtok(s, ","); flag; flag = strtok(NULL, ",")) {
+		found = 0;
+		for (i = 0; sec_flags[i].name != NULL; i++)
+			if (strcasecmp(sec_flags[i].name, flag) == 0) {
+				sac->flags |= sec_flags[i].value;
+				found = 1;
+				break;
+			}
+		if (!found)
+			errx(EXIT_FAILURE, "unrecognized section flag %s",
+			    flag);
+	}
+}
+
+static void
+parse_sec_address_op(struct elfcopy *ecp, int optnum, const char *optname,
+    char *s)
+{
+	struct sec_action	*sac;
+	const char		*name;
+	char			*v;
+	char			 op;
+
+	name = v = s;
+	do {
+		v++;
+	} while (*v != '\0' && *v != '=' && *v != '+' && *v != '-');
+	if (*v == '\0' || *(v + 1) == '\0')
+		errx(EXIT_FAILURE, "invalid format for %s", optname);
+	op = *v;
+	*v++ = '\0';
+	sac = lookup_sec_act(ecp, name, 1);
+	switch (op) {
+	case '=':
+		if (optnum == ECP_CHANGE_SEC_LMA ||
+		    optnum == ECP_CHANGE_SEC_ADDR) {
+			sac->setlma = 1;
+			sac->lma = (uint64_t) strtoull(v, NULL, 0);
+		}
+		if (optnum == ECP_CHANGE_SEC_VMA ||
+		    optnum == ECP_CHANGE_SEC_ADDR) {
+			sac->setvma = 1;
+			sac->vma = (uint64_t) strtoull(v, NULL, 0);
+		}
+		break;
+	case '+':
+		if (optnum == ECP_CHANGE_SEC_LMA ||
+		    optnum == ECP_CHANGE_SEC_ADDR)
+			sac->lma_adjust = (int64_t) strtoll(v, NULL, 0);
+		if (optnum == ECP_CHANGE_SEC_VMA ||
+		    optnum == ECP_CHANGE_SEC_ADDR)
+			sac->vma_adjust = (int64_t) strtoll(v, NULL, 0);
+		break;
+	case '-':
+		if (optnum == ECP_CHANGE_SEC_LMA ||
+		    optnum == ECP_CHANGE_SEC_ADDR)
+			sac->lma_adjust = (int64_t) -strtoll(v, NULL, 0);
+		if (optnum == ECP_CHANGE_SEC_VMA ||
+		    optnum == ECP_CHANGE_SEC_ADDR)
+			sac->vma_adjust = (int64_t) -strtoll(v, NULL, 0);
+		break;
+	default:
+		break;
+	}
+}
+
+static void
+parse_symlist_file(struct elfcopy *ecp, const char *fn, unsigned int op)
+{
+	struct symfile	*sf;
+	struct stat	 sb;
+	FILE		*fp;
+	char		*data, *p, *line, *end, *e, *n;
+
+	if (stat(fn, &sb) == -1)
+		err(EXIT_FAILURE, "stat %s failed", fn);
+
+	/* Check if we already read and processed this file. */
+	STAILQ_FOREACH(sf, &ecp->v_symfile, symfile_list) {
+		if (sf->dev == sb.st_dev && sf->ino == sb.st_ino)
+			goto process_symfile;
+	}
+
+	if ((fp = fopen(fn, "r")) == NULL)
+		err(EXIT_FAILURE, "can not open %s", fn);
+	if ((data = malloc(sb.st_size + 1)) == NULL)
+		err(EXIT_FAILURE, "malloc failed");
+	if (sb.st_size > 0)
+		if (fread(data, sb.st_size, 1, fp) != 1)
+			err(EXIT_FAILURE, "fread failed");
+	fclose(fp);
+	data[sb.st_size] = '\0';
+
+	if ((sf = calloc(1, sizeof(*sf))) == NULL)
+		err(EXIT_FAILURE, "malloc failed");
+	sf->dev = sb.st_dev;
+	sf->ino = sb.st_ino;
+	sf->size = sb.st_size + 1;
+	sf->data = data;
+
+process_symfile:
+
+	/*
+	 * Basically what we do here is to convert EOL to '\0', and remove
+	 * leading and trailing whitespaces for each line.
+	 */
+
+	end = sf->data + sf->size;
+	line = NULL;
+	for(p = sf->data; p < end; p++) {
+		if ((*p == '\t' || *p == ' ') && line == NULL)
+			continue;
+		if (*p == '\r' || *p == '\n' || *p == '\0') {
+			*p = '\0';
+			if (line == NULL)
+				continue;
+
+			/* Skip comment. */
+			if (*line == '#') {
+				line = NULL;
+				continue;
+			}
+
+			e = p - 1;
+			while(e != line && (*e == '\t' || *e == ' '))
+				*e-- = '\0';
+			if (op != SYMOP_REDEF)
+				add_to_symop_list(ecp, line, NULL, op);
+			else {
+				if (strlen(line) < 3)
+					errx(EXIT_FAILURE,
+					    "illegal format for"
+					    " --redefine-sym");
+				for(n = line + 1; n < e; n++) {
+					if (*n == ' ' || *n == '\t') {
+						while(*n == ' ' || *n == '\t')
+							*n++ = '\0';
+						break;
+					}
+				}
+				if (n >= e)
+					errx(EXIT_FAILURE,
+					    "illegal format for"
+					    " --redefine-sym");
+				add_to_symop_list(ecp, line, n, op);
+			}
+			line = NULL;
+			continue;
+		}
+
+		if (line == NULL)
+			line = p;
+	}
+}
+
+static void
+set_input_target(struct elfcopy *ecp, const char *target_name)
+{
+	Elftc_Bfd_Target *tgt;
+
+	if ((tgt = elftc_bfd_find_target(target_name)) == NULL)
+		errx(EXIT_FAILURE, "%s: invalid target name", target_name);
+	ecp->itf = elftc_bfd_target_flavor(tgt);
+}
+
+static void
+set_output_target(struct elfcopy *ecp, const char *target_name)
+{
+	Elftc_Bfd_Target *tgt;
+
+	if ((tgt = elftc_bfd_find_target(target_name)) == NULL)
+		errx(EXIT_FAILURE, "%s: invalid target name", target_name);
+	ecp->otf = elftc_bfd_target_flavor(tgt);
+	if (ecp->otf == ETF_ELF) {
+		ecp->oec = elftc_bfd_target_class(tgt);
+		ecp->oed = elftc_bfd_target_byteorder(tgt);
+		ecp->oem = elftc_bfd_target_machine(tgt);
+	}
+	if (ecp->otf == ETF_EFI || ecp->otf == ETF_PE)
+		ecp->oem = elftc_bfd_target_machine(tgt);
+
+	ecp->otgt = target_name;
+}
+
+static void
+set_osabi(struct elfcopy *ecp, const char *abi)
+{
+	int i, found;
+
+	found = 0;
+	for (i = 0; osabis[i].name != NULL; i++)
+		if (strcasecmp(osabis[i].name, abi) == 0) {
+			ecp->abi = osabis[i].abi;
+			found = 1;
+			break;
+		}
+	if (!found)
+		errx(EXIT_FAILURE, "unrecognized OSABI %s", abi);
+}
+
+#define	ELFCOPY_USAGE_MESSAGE	"\
+Usage: %s [options] infile [outfile]\n\
+  Transform object files.\n\n\
+  Options:\n\
+  -d | -g | --strip-debug      Remove debugging information from the output.\n\
+  -j SECTION | --only-section=SECTION\n\
+                               Copy only the named section to the output.\n\
+  -p | --preserve-dates        Preserve access and modification times.\n\
+  -w | --wildcard              Use shell-style patterns to name symbols.\n\
+  -x | --discard-all           Do not copy non-globals to the output.\n\
+  -I FORMAT | --input-target=FORMAT\n\
+                               Specify object format for the input file.\n\
+  -K SYM | --keep-symbol=SYM   Copy symbol SYM to the output.\n\
+  -L SYM | --localize-symbol=SYM\n\
+                               Make symbol SYM local to the output file.\n\
+  -N SYM | --strip-symbol=SYM  Do not copy symbol SYM to the output.\n\
+  -O FORMAT | --output-target=FORMAT\n\
+                               Specify object format for the output file.\n\
+                               FORMAT should be a target name understood by\n\
+                               elftc_bfd_find_target(3).\n\
+  -R NAME | --remove-section=NAME\n\
+                               Remove the named section.\n\
+  -S | --strip-all             Remove all symbol and relocation information\n\
+                               from the output.\n\
+  -V | --version               Print a version identifier and exit.\n\
+  -W SYM | --weaken-symbol=SYM Mark symbol SYM as weak in the output.\n\
+  -X | --discard-locals        Do not copy compiler generated symbols to\n\
+                               the output.\n\
+  --add-section NAME=FILE      Add the contents of FILE to the ELF object as\n\
+                               a new section named NAME.\n\
+  --adjust-section-vma SECTION{=,+,-}VAL | \\\n\
+    --change-section-address SECTION{=,+,-}VAL\n\
+                               Set or adjust the VMA and the LMA of the\n\
+                               named section by VAL.\n\
+  --adjust-start=INCR | --change-start=INCR\n\
+                               Add INCR to the start address for the ELF\n\
+                               object.\n\
+  --adjust-vma=INCR | --change-addresses=INCR\n\
+                               Increase the VMA and LMA of all sections by\n\
+                               INCR.\n\
+  --adjust-warning | --change-warnings\n\
+                               Issue warnings for non-existent sections.\n\
+  --change-section-lma SECTION{=,+,-}VAL\n\
+                               Set or adjust the LMA address of the named\n\
+                               section by VAL.\n\
+  --change-section-vma SECTION{=,+,-}VAL\n\
+                               Set or adjust the VMA address of the named\n\
+                               section by VAL.\n\
+  --gap-fill=VAL               Fill the gaps between sections with bytes\n\
+                               of value VAL.\n\
+  --localize-hidden            Make all hidden symbols local to the output\n\
+                               file.\n\
+  --no-adjust-warning| --no-change-warnings\n\
+                               Do not issue warnings for non-existent\n\
+                               sections.\n\
+  --only-keep-debug            Copy only debugging information.\n\
+  --output-target=FORMAT       Use the specified format for the output.\n\
+  --pad-to=ADDRESS             Pad the output object up to the given address.\n\
+  --prefix-alloc-sections=STRING\n\
+                               Prefix the section names of all the allocated\n\
+                               sections with STRING.\n\
+  --prefix-sections=STRING     Prefix the section names of all the sections\n\
+                               with STRING.\n\
+  --prefix-symbols=STRING      Prefix the symbol names of all the symbols\n\
+                               with STRING.\n\
+  --rename-section OLDNAME=NEWNAME[,FLAGS]\n\
+                               Rename and optionally change section flags.\n\
+  --set-section-flags SECTION=FLAGS\n\
+                               Set section flags for the named section.\n\
+                               Supported flags are: 'alloc', 'code',\n\
+                               'contents', 'data', 'debug', 'load',\n\
+                               'noload', 'readonly', 'rom', and 'shared'.\n\
+  --set-start=ADDRESS          Set the start address of the ELF object.\n\
+  --srec-forceS3               Only generate S3 S-Records.\n\
+  --srec-len=LEN               Set the maximum length of a S-Record line.\n\
+  --strip-unneeded             Do not copy relocation information.\n"
+
+static void
+elfcopy_usage(void)
+{
+	(void) fprintf(stderr, ELFCOPY_USAGE_MESSAGE, ELFTC_GETPROGNAME());
+	exit(EXIT_FAILURE);
+}
+
+#define	MCS_USAGE_MESSAGE	"\
+Usage: %s [options] file...\n\
+  Manipulate the comment section in an ELF object.\n\n\
+  Options:\n\
+  -a STRING        Append 'STRING' to the comment section.\n\
+  -c               Remove duplicate entries from the comment section.\n\
+  -d               Delete the comment section.\n\
+  -h | --help      Print a help message and exit.\n\
+  -n NAME          Operate on the ELF section with name 'NAME'.\n\
+  -p               Print the contents of the comment section.\n\
+  -V | --version   Print a version identifier and exit.\n"
+
+static void
+mcs_usage(void)
+{
+	(void) fprintf(stderr, MCS_USAGE_MESSAGE, ELFTC_GETPROGNAME());
+	exit(EXIT_FAILURE);
+}
+
+#define	STRIP_USAGE_MESSAGE	"\
+Usage: %s [options] file...\n\
+  Discard information from ELF objects.\n\n\
+  Options:\n\
+  -d | -g | -S | --strip-debug    Remove debugging symbols.\n\
+  -h | --help                     Print a help message.\n\
+  -o FILE | --output-file FILE    Write output to FILE.\n\
+  --only-keep-debug               Keep debugging information only.\n\
+  -p | --preserve-dates           Preserve access and modification times.\n\
+  -s | --strip-all                Remove all symbols.\n\
+  --strip-unneeded                Remove symbols not needed for relocation\n\
+                                  processing.\n\
+  -w | --wildcard                 Use shell-style patterns to name symbols.\n\
+  -x | --discard-all              Discard all non-global symbols.\n\
+  -I TGT| --input-target=TGT      (Accepted, but ignored).\n\
+  -K SYM | --keep-symbol=SYM      Keep symbol 'SYM' in the output.\n\
+  -N SYM | --strip-symbol=SYM     Remove symbol 'SYM' from the output.\n\
+  -O TGT | --output-target=TGT    Set the output file format to 'TGT'.\n\
+  -R SEC | --remove-section=SEC   Remove the section named 'SEC'.\n\
+  -V | --version                  Print a version identifier and exit.\n\
+  -X | --discard-locals           Remove compiler-generated local symbols.\n"
+
+static void
+strip_usage(void)
+{
+	(void) fprintf(stderr, STRIP_USAGE_MESSAGE, ELFTC_GETPROGNAME());
+	exit(EXIT_FAILURE);
+}
+
+static void
+print_version(void)
+{
+	(void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version());
+	exit(EXIT_SUCCESS);
+}
+
+/*
+ * Compare the ending of s with end.
+ */
+static int
+strrcmp(const char *s, const char *end)
+{
+	size_t endlen, slen;
+
+	slen = strlen(s);
+	endlen = strlen(end);
+
+	if (slen >= endlen)
+		s += slen - endlen;
+	return (strcmp(s, end));
+}
+
+int
+main(int argc, char **argv)
+{
+	struct elfcopy *ecp;
+
+	if (elf_version(EV_CURRENT) == EV_NONE)
+		errx(EXIT_FAILURE, "ELF library initialization failed: %s",
+		    elf_errmsg(-1));
+
+	ecp = calloc(1, sizeof(*ecp));
+	if (ecp == NULL)
+		err(EXIT_FAILURE, "calloc failed");
+	memset(ecp, 0, sizeof(*ecp));
+
+	ecp->itf = ecp->otf = ETF_ELF;
+	ecp->iec = ecp->oec = ELFCLASSNONE;
+	ecp->oed = ELFDATANONE;
+	ecp->abi = -1;
+	/* There is always an empty section. */
+	ecp->nos = 1;
+	ecp->fill = 0;
+
+	STAILQ_INIT(&ecp->v_seg);
+	STAILQ_INIT(&ecp->v_sac);
+	STAILQ_INIT(&ecp->v_sadd);
+	STAILQ_INIT(&ecp->v_symop);
+	STAILQ_INIT(&ecp->v_symfile);
+	STAILQ_INIT(&ecp->v_arobj);
+	TAILQ_INIT(&ecp->v_sec);
+
+	if ((ecp->progname = ELFTC_GETPROGNAME()) == NULL)
+		ecp->progname = "elfcopy";
+
+	if (strrcmp(ecp->progname, "strip") == 0)
+		strip_main(ecp, argc, argv);
+	else if (strrcmp(ecp->progname, "mcs") == 0)
+		mcs_main(ecp, argc, argv);
+	else {
+		if (strrcmp(ecp->progname, "elfcopy") != 0 &&
+		    strrcmp(ecp->progname, "objcopy") != 0)
+			warnx("program mode not known, defaulting to elfcopy");
+		elfcopy_main(ecp, argc, argv);
+	}
+
+	free_sec_add(ecp);
+	free_sec_act(ecp);
+	free(ecp);
+
+	exit(EXIT_SUCCESS);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/elfcopy/mcs.1	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,125 @@
+.\" Copyright (c) 2011 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY JOSEPH KOSHY ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL JOSEPH KOSHY BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: mcs.1 2247 2011-11-29 08:41:34Z jkoshy $
+.\"
+.Dd November 29, 2011
+.Os
+.Dt MCS 1
+.Sh NAME
+.Nm mcs
+.Nd manipulate the comment section of an ELF object
+.Sh SYNOPSIS
+.Nm
+.Op Fl a Ar string
+.Op Fl c
+.Op Fl n Ar name
+.Op Fl p
+.Ar
+.Nm
+.Fl d
+.Op Fl n Ar name
+.Ar
+.Nm
+.Fl h | Fl -help
+.Nm
+.Fl V | Fl -version
+.Sh DESCRIPTION
+The
+.Nm
+utility is used to manipulate comment sections in an ELF object.
+If a command-line argument
+.Ar file
+names an
+.Xr ar 1
+archive, then
+.Nm
+will operate on the ELF objects contained in the archive.
+.Pp
+By default
+.Nm
+operates on the ELF section named
+.Dq .comment .
+This may be changed using the
+.Fl n
+option.
+.Pp
+The
+.Nm
+utility supports the following options:
+.Bl -tag -width ".Fl a Ar string"
+.It Fl a Ar string
+Append the text in
+.Ar string
+to the comment section.
+This option may be specified multiple times.
+.It Fl c
+Compress the comment section by removing duplicate entries.
+.It Fl d
+Delete the comment section from the ELF object.
+.It Fl h | Fl -help
+Display a usage message and exit.
+.It Fl n Ar name
+Operate on the section named
+.Ar name .
+.It Fl p
+Print the contents of the comment section.
+This step is taken after actions specified by the
+.Fl a
+and
+.Fl c
+options (if any) are completed.
+.It Fl V | Fl -version
+Print a version identifier and exit.
+.El
+.Sh COMPATIBILITY
+The behavior of the
+.Nm
+utility differs from its SVR4 counterpart in the following ways:
+.Bl -bullet -compact
+.It
+If the
+.Fl d
+option is specified, it causes any
+.Fl a ,
+.Fl c
+and
+.Fl p
+options present to be ignored.
+.It
+The order of options
+.Fl a ,
+.Fl c ,
+.Fl d ,
+and
+.Fl p
+on the command line is not significant.
+.El
+.Sh DIAGNOSTICS
+.Ex -std
+.Sh SEE ALSO
+.Xr ar 1 ,
+.Xr elfcopy 1 ,
+.Xr ld 1 ,
+.Xr nm 1 ,
+.Xr strip 1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/elfcopy/os.FreeBSD.mk	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,4 @@
+.if !defined(LIBELF_AR)
+DPADD+= ${LIBBZ2}
+LDADD+= -lbz2
+.endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/elfcopy/pe.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,236 @@
+/*-
+ * Copyright (c) 2016 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <err.h>
+#include <gelf.h>
+#include <libpe.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "elfcopy.h"
+
+ELFTC_VCSID("$Id: pe.c 3508 2016-12-27 06:19:39Z kaiwang27 $");
+
+/* Convert ELF object to Portable Executable (PE). */
+void
+create_pe(struct elfcopy *ecp, int ifd, int ofd)
+{
+	Elf *e;
+	Elf_Scn *scn;
+	Elf_Data *d;
+	GElf_Ehdr eh;
+	GElf_Shdr sh;
+	PE *pe;
+	PE_Scn *ps;
+	PE_SecHdr psh;
+	PE_CoffHdr pch;
+	PE_OptHdr poh;
+	PE_Object po;
+	PE_Buffer *pb;
+	const char *name;
+	size_t indx;
+	time_t timestamp;
+	int elferr;
+
+	if (ecp->otf == ETF_EFI || ecp->oem == EM_X86_64)
+		po = PE_O_PE32P;
+	else
+		po = PE_O_PE32;
+
+	if ((e = elf_begin(ifd, ELF_C_READ, NULL)) == NULL)
+		errx(EXIT_FAILURE, "elf_begin() failed: %s",
+		    elf_errmsg(-1));
+
+	if (gelf_getehdr(e, &eh) == NULL)
+		errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
+		    elf_errmsg(-1));
+
+	if (elf_getshstrndx(e, &indx) == 0)
+		errx(EXIT_FAILURE, "elf_getshstrndx() failed: %s",
+		    elf_errmsg(-1));
+
+	if ((pe = pe_init(ofd, PE_C_WRITE, po)) == NULL)
+		err(EXIT_FAILURE, "pe_init() failed");
+
+	/* Setup PE COFF header. */
+	memset(&pch, 0, sizeof(pch));
+	switch (ecp->oem) {
+	case EM_386:
+		pch.ch_machine = IMAGE_FILE_MACHINE_I386;
+		break;
+	case EM_X86_64:
+		pch.ch_machine = IMAGE_FILE_MACHINE_AMD64;
+		break;
+	default:
+		pch.ch_machine = IMAGE_FILE_MACHINE_UNKNOWN;
+		break;
+	}
+	if (elftc_timestamp(&timestamp) != 0)
+		err(EXIT_FAILURE, "elftc_timestamp");
+	pch.ch_timestamp = (uint32_t) timestamp;
+	if (pe_update_coff_header(pe, &pch) < 0)
+		err(EXIT_FAILURE, "pe_update_coff_header() failed");
+
+	/* Setup PE optional header. */
+	memset(&poh, 0, sizeof(poh));
+	if (ecp->otf == ETF_EFI)
+		poh.oh_subsystem = IMAGE_SUBSYSTEM_EFI_APPLICATION;
+	poh.oh_entry = (uint32_t) eh.e_entry;
+
+	/*
+	 * Default section alignment and file alignment. (Here the
+	 * section alignment is set to the default page size of the
+	 * archs supported. We should use different section alignment
+	 * for some arch. (e.g. IA64)
+	 */
+	poh.oh_secalign = 0x1000;
+	poh.oh_filealign = 0x200;
+
+	/* Copy sections. */
+	scn = NULL;
+	while ((scn = elf_nextscn(e, scn)) != NULL) {
+
+		/*
+		 * Read in ELF section.
+		 */
+
+		if (gelf_getshdr(scn, &sh) == NULL) {
+			warnx("gelf_getshdr() failed: %s", elf_errmsg(-1));
+			(void) elf_errno();
+			continue;
+		}
+		if ((name = elf_strptr(e, indx, sh.sh_name)) ==
+		    NULL) {
+			warnx("elf_strptr() failed: %s", elf_errmsg(-1));
+			(void) elf_errno();
+			continue;
+		}
+
+		/* Skip sections unneeded. */
+		if (strcmp(name, ".shstrtab") == 0 ||
+		    strcmp(name, ".symtab") == 0 ||
+		    strcmp(name, ".strtab") == 0)
+			continue;
+
+		if ((d = elf_getdata(scn, NULL)) == NULL) {
+			warnx("elf_getdata() failed: %s", elf_errmsg(-1));
+			(void) elf_errno();
+			continue;
+		}
+
+		if (strcmp(name, ".text") == 0) {
+			poh.oh_textbase = (uint32_t) sh.sh_addr;
+			poh.oh_textsize = (uint32_t) roundup(sh.sh_size,
+			    poh.oh_filealign);
+		} else {
+			if (po == PE_O_PE32 && strcmp(name, ".data") == 0)
+				poh.oh_database = sh.sh_addr;
+			if (sh.sh_type == SHT_NOBITS)
+				poh.oh_bsssize += (uint32_t)
+				    roundup(sh.sh_size, poh.oh_filealign);
+			else if (sh.sh_flags & SHF_ALLOC)
+				poh.oh_datasize += (uint32_t)
+				    roundup(sh.sh_size, poh.oh_filealign);
+		}
+
+		/*
+		 * Create PE/COFF section.
+		 */
+
+		if ((ps = pe_newscn(pe)) == NULL) {
+			warn("pe_newscn() failed");
+			continue;
+		}
+
+		/*
+		 * Setup PE/COFF section header. The section name is not
+		 * NUL-terminated if its length happens to be 8. Long
+		 * section name should be truncated for PE image according
+		 * to the PE/COFF specification.
+		 */
+		memset(&psh, 0, sizeof(psh));
+		strncpy(psh.sh_name, name, sizeof(psh.sh_name));
+		psh.sh_addr = sh.sh_addr;
+		psh.sh_virtsize = sh.sh_size;
+		if (sh.sh_type != SHT_NOBITS)
+			psh.sh_rawsize = roundup(sh.sh_size, poh.oh_filealign);
+		else
+			psh.sh_char |= IMAGE_SCN_CNT_UNINITIALIZED_DATA;
+
+		/*
+		 * Translate ELF section flags to PE/COFF section flags.
+		 */
+		psh.sh_char |= IMAGE_SCN_MEM_READ;
+		if (sh.sh_flags & SHF_WRITE)
+			psh.sh_char |= IMAGE_SCN_MEM_WRITE;
+		if (sh.sh_flags & SHF_EXECINSTR)
+			psh.sh_char |= IMAGE_SCN_MEM_EXECUTE |
+			    IMAGE_SCN_CNT_CODE;
+		if ((sh.sh_flags & SHF_ALLOC) && (psh.sh_char & 0xF0) == 0)
+			psh.sh_char |= IMAGE_SCN_CNT_INITIALIZED_DATA;
+
+		/* Mark relocation section "discardable". */
+		if (strcmp(name, ".reloc") == 0)
+			psh.sh_char |= IMAGE_SCN_MEM_DISCARDABLE;
+
+		if (pe_update_section_header(ps, &psh) < 0) {
+			warn("pe_update_section_header() failed");
+			continue;
+		}
+
+		/* Copy section content. */
+		if ((pb = pe_newbuffer(ps)) == NULL) {
+			warn("pe_newbuffer() failed");
+			continue;
+		}
+		pb->pb_align = 1;
+		pb->pb_off = 0;
+		if (sh.sh_type != SHT_NOBITS) {
+			pb->pb_size = roundup(sh.sh_size, poh.oh_filealign);
+			if ((pb->pb_buf = calloc(1, pb->pb_size)) == NULL) {
+				warn("calloc failed");
+				continue;
+			}
+			memcpy(pb->pb_buf, d->d_buf, sh.sh_size);
+		}
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		warnx("elf_nextscn() failed: %s", elf_errmsg(elferr));
+
+	/* Update PE optional header. */
+	if (pe_update_opt_header(pe, &poh) < 0)
+		err(EXIT_FAILURE, "pe_update_opt_header() failed");
+
+	/* Write out PE/COFF object. */
+	if (pe_update(pe) < 0)
+		err(EXIT_FAILURE, "pe_update() failed");
+
+	pe_finish(pe);
+	elf_end(e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/elfcopy/sections.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,1741 @@
+/*-
+ * Copyright (c) 2007-2011,2014 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <err.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "elfcopy.h"
+
+ELFTC_VCSID("$Id: sections.c 3443 2016-04-15 18:57:54Z kaiwang27 $");
+
+static void	add_gnu_debuglink(struct elfcopy *ecp);
+static uint32_t calc_crc32(const char *p, size_t len, uint32_t crc);
+static void	check_section_rename(struct elfcopy *ecp, struct section *s);
+static void	filter_reloc(struct elfcopy *ecp, struct section *s);
+static int	get_section_flags(struct elfcopy *ecp, const char *name);
+static void	insert_sections(struct elfcopy *ecp);
+static void	insert_to_strtab(struct section *t, const char *s);
+static int	is_append_section(struct elfcopy *ecp, const char *name);
+static int	is_compress_section(struct elfcopy *ecp, const char *name);
+static int	is_debug_section(const char *name);
+static int	is_dwo_section(const char *name);
+static int	is_modify_section(struct elfcopy *ecp, const char *name);
+static int	is_print_section(struct elfcopy *ecp, const char *name);
+static int	lookup_string(struct section *t, const char *s);
+static void	modify_section(struct elfcopy *ecp, struct section *s);
+static void	pad_section(struct elfcopy *ecp, struct section *s);
+static void	print_data(const char *d, size_t sz);
+static void	print_section(struct section *s);
+static void	*read_section(struct section *s, size_t *size);
+static void	update_reloc(struct elfcopy *ecp, struct section *s);
+static void	update_section_group(struct elfcopy *ecp, struct section *s);
+
+int
+is_remove_section(struct elfcopy *ecp, const char *name)
+{
+
+	/* Always keep section name table */
+	if (strcmp(name, ".shstrtab") == 0)
+		return 0;
+	if (strcmp(name, ".symtab") == 0 ||
+	    strcmp(name, ".strtab") == 0) {
+		if (ecp->strip == STRIP_ALL && lookup_symop_list(
+		    ecp, NULL, SYMOP_KEEP) == NULL)
+			return (1);
+		else
+			return (0);
+	}
+
+	if (ecp->strip == STRIP_DWO && is_dwo_section(name))
+		return (1);
+	if (ecp->strip == STRIP_NONDWO && !is_dwo_section(name))
+		return (1);
+
+	if (is_debug_section(name)) {
+		if (ecp->strip == STRIP_ALL ||
+		    ecp->strip == STRIP_DEBUG ||
+		    ecp->strip == STRIP_UNNEEDED ||
+		    (ecp->flags & DISCARD_LOCAL))
+			return (1);
+		if (ecp->strip == STRIP_NONDEBUG)
+			return (0);
+	}
+
+	if ((ecp->flags & SEC_REMOVE) || (ecp->flags & SEC_COPY)) {
+		struct sec_action *sac;
+
+		sac = lookup_sec_act(ecp, name, 0);
+		if ((ecp->flags & SEC_REMOVE) && sac != NULL && sac->remove)
+			return (1);
+		if ((ecp->flags & SEC_COPY) && (sac == NULL || !sac->copy))
+			return (1);
+	}
+
+	return (0);
+}
+
+/*
+ * Relocation section needs to be removed if the section it applies to
+ * will be removed.
+ */
+int
+is_remove_reloc_sec(struct elfcopy *ecp, uint32_t sh_info)
+{
+	const char	*name;
+	GElf_Shdr	 ish;
+	Elf_Scn		*is;
+	size_t		 indx;
+	int		 elferr;
+
+	if (elf_getshstrndx(ecp->ein, &indx) == 0)
+		errx(EXIT_FAILURE, "elf_getshstrndx failed: %s",
+		    elf_errmsg(-1));
+
+	is = NULL;
+	while ((is = elf_nextscn(ecp->ein, is)) != NULL) {
+		if (sh_info == elf_ndxscn(is)) {
+			if (gelf_getshdr(is, &ish) == NULL)
+				errx(EXIT_FAILURE, "gelf_getshdr failed: %s",
+				    elf_errmsg(-1));
+			if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) ==
+			    NULL)
+				errx(EXIT_FAILURE, "elf_strptr failed: %s",
+				    elf_errmsg(-1));
+			if (is_remove_section(ecp, name))
+				return (1);
+			else
+				return (0);
+		}
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		errx(EXIT_FAILURE, "elf_nextscn failed: %s",
+		    elf_errmsg(elferr));
+
+	/* Remove reloc section if we can't find the target section. */
+	return (1);
+}
+
+static int
+is_append_section(struct elfcopy *ecp, const char *name)
+{
+	struct sec_action *sac;
+
+	sac = lookup_sec_act(ecp, name, 0);
+	if (sac != NULL && sac->append != 0 && sac->string != NULL)
+		return (1);
+
+	return (0);
+}
+
+static int
+is_compress_section(struct elfcopy *ecp, const char *name)
+{
+	struct sec_action *sac;
+
+	sac = lookup_sec_act(ecp, name, 0);
+	if (sac != NULL && sac->compress != 0)
+		return (1);
+
+	return (0);
+}
+
+static void
+check_section_rename(struct elfcopy *ecp, struct section *s)
+{
+	struct sec_action *sac;
+	char *prefix;
+	size_t namelen;
+
+	if (s->pseudo)
+		return;
+
+	sac = lookup_sec_act(ecp, s->name, 0);
+	if (sac != NULL && sac->rename)
+		s->name = sac->newname;
+
+	if (!strcmp(s->name, ".symtab") ||
+	    !strcmp(s->name, ".strtab") ||
+	    !strcmp(s->name, ".shstrtab"))
+		return;
+
+	prefix = NULL;
+	if (s->loadable && ecp->prefix_alloc != NULL)
+		prefix = ecp->prefix_alloc;
+	else if (ecp->prefix_sec != NULL)
+		prefix = ecp->prefix_sec;
+
+	if (prefix != NULL) {
+		namelen = strlen(s->name) + strlen(prefix) + 1;
+		if ((s->newname = malloc(namelen)) == NULL)
+			err(EXIT_FAILURE, "malloc failed");
+		snprintf(s->newname, namelen, "%s%s", prefix, s->name);
+		s->name = s->newname;
+	}
+}
+
+static int
+get_section_flags(struct elfcopy *ecp, const char *name)
+{
+	struct sec_action *sac;
+
+	sac = lookup_sec_act(ecp, name, 0);
+	if (sac != NULL && sac->flags)
+		return sac->flags;
+
+	return (0);
+}
+
+/*
+ * Determine whether the section are debugging section.
+ * According to libbfd, debugging sections are recognized
+ * only by name.
+ */
+static int
+is_debug_section(const char *name)
+{
+	const char *dbg_sec[] = {
+		".apple_",
+		".debug",
+		".gnu.linkonce.wi.",
+		".line",
+		".stab",
+		NULL
+	};
+	const char **p;
+
+	for(p = dbg_sec; *p; p++) {
+		if (strncmp(name, *p, strlen(*p)) == 0)
+			return (1);
+	}
+
+	return (0);
+}
+
+static int
+is_dwo_section(const char *name)
+{
+	size_t len;
+
+	if ((len = strlen(name)) > 4 && strcmp(name + len - 4, ".dwo") == 0)
+		return (1);
+	return (0);
+}
+
+static int
+is_print_section(struct elfcopy *ecp, const char *name)
+{
+	struct sec_action *sac;
+
+	sac = lookup_sec_act(ecp, name, 0);
+	if (sac != NULL && sac->print != 0)
+		return (1);
+
+	return (0);
+}
+
+static int
+is_modify_section(struct elfcopy *ecp, const char *name)
+{
+
+	if (is_append_section(ecp, name) ||
+	    is_compress_section(ecp, name))
+		return (1);
+
+	return (0);
+}
+
+struct sec_action*
+lookup_sec_act(struct elfcopy *ecp, const char *name, int add)
+{
+	struct sec_action *sac;
+
+	if (name == NULL)
+		return NULL;
+
+	STAILQ_FOREACH(sac, &ecp->v_sac, sac_list) {
+		if (strcmp(name, sac->name) == 0)
+			return sac;
+	}
+
+	if (add == 0)
+		return NULL;
+
+	if ((sac = malloc(sizeof(*sac))) == NULL)
+		errx(EXIT_FAILURE, "not enough memory");
+	memset(sac, 0, sizeof(*sac));
+	sac->name = name;
+	STAILQ_INSERT_TAIL(&ecp->v_sac, sac, sac_list);
+
+	return (sac);
+}
+
+void
+free_sec_act(struct elfcopy *ecp)
+{
+	struct sec_action *sac, *sac_temp;
+
+	STAILQ_FOREACH_SAFE(sac, &ecp->v_sac, sac_list, sac_temp) {
+		STAILQ_REMOVE(&ecp->v_sac, sac, sec_action, sac_list);
+		free(sac);
+	}
+}
+
+void
+insert_to_sec_list(struct elfcopy *ecp, struct section *sec, int tail)
+{
+	struct section *s;
+
+	if (!tail) {
+		TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
+			if (sec->off < s->off) {
+				TAILQ_INSERT_BEFORE(s, sec, sec_list);
+				goto inc_nos;
+			}
+		}
+	}
+
+	TAILQ_INSERT_TAIL(&ecp->v_sec, sec, sec_list);
+
+inc_nos:
+	if (sec->pseudo == 0)
+		ecp->nos++;
+}
+
+/*
+ * First step of section creation: create scn and internal section
+ * structure, discard sections to be removed.
+ */
+void
+create_scn(struct elfcopy *ecp)
+{
+	struct section	*s;
+	const char	*name;
+	Elf_Scn		*is;
+	GElf_Shdr	 ish;
+	size_t		 indx;
+	uint64_t	 oldndx, newndx;
+	int		 elferr, sec_flags, reorder;
+
+	/*
+	 * Insert a pseudo section that contains the ELF header
+	 * and program header. Used as reference for section offset
+	 * or load address adjustment.
+	 */
+	if ((s = calloc(1, sizeof(*s))) == NULL)
+		err(EXIT_FAILURE, "calloc failed");
+	s->off = 0;
+	s->sz = gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT) +
+	    gelf_fsize(ecp->eout, ELF_T_PHDR, ecp->ophnum, EV_CURRENT);
+	s->align = 1;
+	s->pseudo = 1;
+	s->loadable = add_to_inseg_list(ecp, s);
+	insert_to_sec_list(ecp, s, 0);
+
+	/* Create internal .shstrtab section. */
+	init_shstrtab(ecp);
+
+	if (elf_getshstrndx(ecp->ein, &indx) == 0)
+		errx(EXIT_FAILURE, "elf_getshstrndx failed: %s",
+		    elf_errmsg(-1));
+
+	reorder = 0;
+	is = NULL;
+	while ((is = elf_nextscn(ecp->ein, is)) != NULL) {
+		if (gelf_getshdr(is, &ish) == NULL)
+			errx(EXIT_FAILURE, "gelf_getshdr failed: %s",
+			    elf_errmsg(-1));
+		if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) == NULL)
+			errx(EXIT_FAILURE, "elf_strptr failed: %s",
+			    elf_errmsg(-1));
+
+		/* Skip sections to be removed. */
+		if (is_remove_section(ecp, name))
+			continue;
+
+		/*
+		 * Relocation section need to be remove if the section
+		 * it applies will be removed.
+		 */
+		if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA)
+			if (ish.sh_info != 0 &&
+			    is_remove_reloc_sec(ecp, ish.sh_info))
+				continue;
+
+		/*
+		 * Section groups should be removed if symbol table will
+		 * be removed. (section group's signature stored in symbol
+		 * table)
+		 */
+		if (ish.sh_type == SHT_GROUP && ecp->strip == STRIP_ALL)
+			continue;
+
+		/* Get section flags set by user. */
+		sec_flags = get_section_flags(ecp, name);
+
+		/* Create internal section object. */
+		if (strcmp(name, ".shstrtab") != 0) {
+			if ((s = calloc(1, sizeof(*s))) == NULL)
+				err(EXIT_FAILURE, "calloc failed");
+			s->name		= name;
+			s->is		= is;
+			s->off		= ish.sh_offset;
+			s->sz		= ish.sh_size;
+			s->align	= ish.sh_addralign;
+			s->type		= ish.sh_type;
+			s->flags	= ish.sh_flags;
+			s->vma		= ish.sh_addr;
+
+			/*
+			 * Search program headers to determine whether section
+			 * is loadable, but if user explicitly set section flags
+			 * while neither "load" nor "alloc" is set, we make the
+			 * section unloadable.
+			 *
+			 * Sections in relocatable object is loadable if
+			 * section flag SHF_ALLOC is set.
+			 */
+			if (sec_flags &&
+			    (sec_flags & (SF_LOAD | SF_ALLOC)) == 0)
+				s->loadable = 0;
+			else {
+				s->loadable = add_to_inseg_list(ecp, s);
+				if ((ecp->flags & RELOCATABLE) &&
+				    (ish.sh_flags & SHF_ALLOC))
+					s->loadable = 1;
+			}
+		} else {
+			/* Assuming .shstrtab is "unloadable". */
+			s		= ecp->shstrtab;
+			s->off		= ish.sh_offset;
+		}
+
+		oldndx = newndx = SHN_UNDEF;
+		if (strcmp(name, ".symtab") != 0 &&
+		    strcmp(name, ".strtab") != 0) {
+			if (!strcmp(name, ".shstrtab")) {
+				/*
+				 * Add sections specified by --add-section and
+				 * gnu debuglink. we want these sections have
+				 * smaller index than .shstrtab section.
+				 */
+				if (ecp->debuglink != NULL)
+					add_gnu_debuglink(ecp);
+				if (ecp->flags & SEC_ADD)
+					insert_sections(ecp);
+			}
+ 			if ((s->os = elf_newscn(ecp->eout)) == NULL)
+				errx(EXIT_FAILURE, "elf_newscn failed: %s",
+				    elf_errmsg(-1));
+			if ((newndx = elf_ndxscn(s->os)) == SHN_UNDEF)
+				errx(EXIT_FAILURE, "elf_ndxscn failed: %s",
+				    elf_errmsg(-1));
+		}
+		if ((oldndx = elf_ndxscn(is)) == SHN_UNDEF)
+			errx(EXIT_FAILURE, "elf_ndxscn failed: %s",
+			    elf_errmsg(-1));
+		if (oldndx != SHN_UNDEF && newndx != SHN_UNDEF)
+			ecp->secndx[oldndx] = newndx;
+
+		/*
+		 * If strip action is STRIP_NONDEBUG(only keep debug),
+		 * change sections type of loadable sections and section
+		 * groups to SHT_NOBITS, and the content of those sections
+		 * will be discarded. However, SHT_NOTE sections should
+		 * be kept.
+		 */
+		if (ecp->strip == STRIP_NONDEBUG) {
+			if (((ish.sh_flags & SHF_ALLOC) ||
+			    (ish.sh_flags & SHF_GROUP)) &&
+			    ish.sh_type != SHT_NOTE)
+				s->type = SHT_NOBITS;
+		}
+
+		check_section_rename(ecp, s);
+
+		/* create section header based on input object. */
+		if (strcmp(name, ".symtab") != 0 &&
+		    strcmp(name, ".strtab") != 0 &&
+		    strcmp(name, ".shstrtab") != 0) {
+			copy_shdr(ecp, s, NULL, 0, sec_flags);
+			/*
+			 * elfcopy puts .symtab, .strtab and .shstrtab
+			 * sections in the end of the output object.
+			 * If the input objects have more sections
+			 * after any of these 3 sections, the section
+			 * table will be reordered. section symbols
+			 * should be regenerated for relocations.
+			 */
+			if (reorder)
+				ecp->flags &= ~SYMTAB_INTACT;
+		} else
+			reorder = 1;
+
+		if (strcmp(name, ".symtab") == 0) {
+			ecp->flags |= SYMTAB_EXIST;
+			ecp->symtab = s;
+		}
+		if (strcmp(name, ".strtab") == 0)
+			ecp->strtab = s;
+
+		insert_to_sec_list(ecp, s, 0);
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		errx(EXIT_FAILURE, "elf_nextscn failed: %s",
+		    elf_errmsg(elferr));
+}
+
+struct section *
+insert_shtab(struct elfcopy *ecp, int tail)
+{
+	struct section	*s, *shtab;
+	GElf_Ehdr	 ieh;
+	int		 nsecs;
+
+	/*
+	 * Treat section header table as a "pseudo" section, insert it
+	 * into section list, so later it will get sorted and resynced
+	 * just as normal sections.
+	 */
+	if ((shtab = calloc(1, sizeof(*shtab))) == NULL)
+		errx(EXIT_FAILURE, "calloc failed");
+	if (!tail) {
+		/*
+		 * "shoff" of input object is used as a hint for section
+		 * resync later.
+		 */
+		if (gelf_getehdr(ecp->ein, &ieh) == NULL)
+			errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
+			    elf_errmsg(-1));
+		shtab->off = ieh.e_shoff;
+	} else
+		shtab->off = 0;
+	/* Calculate number of sections in the output object. */
+	nsecs = 0;
+	TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
+		if (!s->pseudo)
+			nsecs++;
+	}
+	/* Remember there is always a null section, so we +1 here. */
+	shtab->sz = gelf_fsize(ecp->eout, ELF_T_SHDR, nsecs + 1, EV_CURRENT);
+	if (shtab->sz == 0)
+		errx(EXIT_FAILURE, "gelf_fsize() failed: %s", elf_errmsg(-1));
+	shtab->align = (ecp->oec == ELFCLASS32 ? 4 : 8);
+	shtab->loadable = 0;
+	shtab->pseudo = 1;
+	insert_to_sec_list(ecp, shtab, tail);
+
+	return (shtab);
+}
+
+void
+copy_content(struct elfcopy *ecp)
+{
+	struct section *s;
+
+	TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
+		/* Skip pseudo section. */
+		if (s->pseudo)
+			continue;
+
+		/* Skip special sections. */
+		if (strcmp(s->name, ".symtab") == 0 ||
+		    strcmp(s->name, ".strtab") == 0 ||
+		    strcmp(s->name, ".shstrtab") == 0)
+			continue;
+
+		/*
+		 * If strip action is STRIP_ALL, relocation info need
+		 * to be stripped. Skip filtering otherwisw.
+		 */
+		if (ecp->strip == STRIP_ALL &&
+		    (s->type == SHT_REL || s->type == SHT_RELA))
+			filter_reloc(ecp, s);
+
+		/*
+		 * The section indices in the SHT_GROUP section needs
+		 * to be updated since we might have stripped some
+		 * sections and changed section numbering.
+		 */
+		if (s->type == SHT_GROUP)
+			update_section_group(ecp, s);
+
+		if (is_modify_section(ecp, s->name))
+			modify_section(ecp, s);
+
+		copy_data(s);
+
+		/*
+		 * If symbol table is modified, relocation info might
+		 * need update, as symbol index may have changed.
+		 */
+		if ((ecp->flags & SYMTAB_INTACT) == 0 &&
+		    (ecp->flags & SYMTAB_EXIST) &&
+		    (s->type == SHT_REL || s->type == SHT_RELA))
+			update_reloc(ecp, s);
+
+		if (is_print_section(ecp, s->name))
+			print_section(s);
+	}
+}
+
+
+/*
+ * Update section group section. The section indices in the SHT_GROUP
+ * section need update after section numbering changed.
+ */
+static void
+update_section_group(struct elfcopy *ecp, struct section *s)
+{
+	GElf_Shdr	 ish;
+	Elf_Data	*id;
+	uint32_t	*ws, *wd;
+	uint64_t	 n;
+	size_t		 ishnum;
+	int		 i, j;
+
+	if (!elf_getshnum(ecp->ein, &ishnum))
+		errx(EXIT_FAILURE, "elf_getshnum failed: %s",
+		    elf_errmsg(-1));
+
+	if (gelf_getshdr(s->is, &ish) == NULL)
+		errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
+		    elf_errmsg(-1));
+
+	if ((id = elf_getdata(s->is, NULL)) == NULL)
+		errx(EXIT_FAILURE, "elf_getdata() failed: %s",
+		    elf_errmsg(-1));
+
+	if (ish.sh_size == 0)
+		return;
+
+	if (ish.sh_entsize == 0)
+		ish.sh_entsize = 4;
+
+	ws = id->d_buf;
+
+	/* We only support COMDAT section. */
+#ifndef GRP_COMDAT
+#define	GRP_COMDAT 0x1
+#endif
+	if ((*ws & GRP_COMDAT) == 0)
+		return;
+
+	if ((s->buf = malloc(ish.sh_size)) == NULL)
+		err(EXIT_FAILURE, "malloc failed");
+
+	s->sz = ish.sh_size;
+
+	wd = s->buf;
+
+	/* Copy the flag word as-is. */
+	*wd = *ws;
+
+	/* Update the section indices. */
+	n = ish.sh_size / ish.sh_entsize;
+	for(i = 1, j = 1; (uint64_t)i < n; i++) {
+		if (ws[i] != SHN_UNDEF && ws[i] < ishnum &&
+		    ecp->secndx[ws[i]] != 0)
+			wd[j++] = ecp->secndx[ws[i]];
+		else
+			s->sz -= 4;
+	}
+
+	s->nocopy = 1;
+}
+
+/*
+ * Filter relocation entries, only keep those entries whose
+ * symbol is in the keep list.
+ */
+static void
+filter_reloc(struct elfcopy *ecp, struct section *s)
+{
+	const char	*name;
+	GElf_Shdr	 ish;
+	GElf_Rel	 rel;
+	GElf_Rela	 rela;
+	Elf32_Rel	*rel32;
+	Elf64_Rel	*rel64;
+	Elf32_Rela	*rela32;
+	Elf64_Rela	*rela64;
+	Elf_Data	*id;
+	uint64_t	 cap, n, nrels, sym;
+	int		 elferr, i;
+
+	if (gelf_getshdr(s->is, &ish) == NULL)
+		errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
+		    elf_errmsg(-1));
+
+	/* We don't want to touch relocation info for dynamic symbols. */
+	if ((ecp->flags & SYMTAB_EXIST) == 0) {
+		/*
+		 * No symbol table in output.  If sh_link points to a section
+		 * that exists in the output object, this relocation section
+		 * is for dynamic symbols.  Don't touch it.
+		 */
+		if (ish.sh_link != 0 && ecp->secndx[ish.sh_link] != 0)
+			return;
+	} else {
+		/* Symbol table exist, check if index equals. */
+		if (ish.sh_link != elf_ndxscn(ecp->symtab->is))
+			return;
+	}
+
+#define	COPYREL(REL, SZ) do {					\
+	if (nrels == 0) {					\
+		if ((REL##SZ = malloc(cap *			\
+		    sizeof(*REL##SZ))) == NULL)			\
+			err(EXIT_FAILURE, "malloc failed");	\
+	}							\
+	if (nrels >= cap) {					\
+		cap *= 2;					\
+		if ((REL##SZ = realloc(REL##SZ, cap *		\
+		    sizeof(*REL##SZ))) == NULL)			\
+			err(EXIT_FAILURE, "realloc failed");	\
+	}							\
+	REL##SZ[nrels].r_offset = REL.r_offset;			\
+	REL##SZ[nrels].r_info	= REL.r_info;			\
+	if (s->type == SHT_RELA)				\
+		rela##SZ[nrels].r_addend = rela.r_addend;	\
+	nrels++;						\
+} while (0)
+
+	nrels = 0;
+	cap = 4;		/* keep list is usually small. */
+	rel32 = NULL;
+	rel64 = NULL;
+	rela32 = NULL;
+	rela64 = NULL;
+	if ((id = elf_getdata(s->is, NULL)) == NULL)
+		errx(EXIT_FAILURE, "elf_getdata() failed: %s",
+		    elf_errmsg(-1));
+	n = ish.sh_size / ish.sh_entsize;
+	for(i = 0; (uint64_t)i < n; i++) {
+		if (s->type == SHT_REL) {
+			if (gelf_getrel(id, i, &rel) != &rel)
+				errx(EXIT_FAILURE, "gelf_getrel failed: %s",
+				    elf_errmsg(-1));
+			sym = GELF_R_SYM(rel.r_info);
+		} else {
+			if (gelf_getrela(id, i, &rela) != &rela)
+				errx(EXIT_FAILURE, "gelf_getrel failed: %s",
+				    elf_errmsg(-1));
+			sym = GELF_R_SYM(rela.r_info);
+		}
+		/*
+		 * If a relocation references a symbol and we are omitting
+		 * either that symbol or the entire symbol table we cannot
+		 * produce valid output, and so just omit the relocation.
+		 * Broken output like this is generally not useful, but some
+		 * uses of elfcopy/strip rely on it - for example, GCC's build
+		 * process uses it to check for build reproducibility by
+		 * stripping objects and comparing them.
+		 *
+		 * Relocations that do not reference a symbol are retained.
+		 */
+		if (sym != 0) {
+			if (ish.sh_link == 0 || ecp->secndx[ish.sh_link] == 0)
+				continue;
+			name = elf_strptr(ecp->ein, elf_ndxscn(ecp->strtab->is),
+			    sym);
+			if (name == NULL)
+				errx(EXIT_FAILURE, "elf_strptr failed: %s",
+				    elf_errmsg(-1));
+			if (lookup_symop_list(ecp, name, SYMOP_KEEP) == NULL)
+				continue;
+		}
+		if (ecp->oec == ELFCLASS32) {
+			if (s->type == SHT_REL)
+				COPYREL(rel, 32);
+			else
+				COPYREL(rela, 32);
+		} else {
+			if (s->type == SHT_REL)
+				COPYREL(rel, 64);
+			else
+				COPYREL(rela, 64);
+		}
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		errx(EXIT_FAILURE, "elf_getdata() failed: %s",
+		    elf_errmsg(elferr));
+
+	if (ecp->oec == ELFCLASS32) {
+		if (s->type == SHT_REL)
+			s->buf = rel32;
+		else
+			s->buf = rela32;
+	} else {
+		if (s->type == SHT_REL)
+			s->buf = rel64;
+		else
+			s->buf = rela64;
+	}
+	s->sz = gelf_fsize(ecp->eout, (s->type == SHT_REL ? ELF_T_REL :
+	    ELF_T_RELA), nrels, EV_CURRENT);
+	s->nocopy = 1;
+}
+
+static void
+update_reloc(struct elfcopy *ecp, struct section *s)
+{
+	GElf_Shdr	 osh;
+	GElf_Rel	 rel;
+	GElf_Rela	 rela;
+	Elf_Data	*od;
+	uint64_t	 n;
+	int		 i;
+
+#define UPDATEREL(REL) do {						\
+	if (gelf_get##REL(od, i, &REL) != &REL)				\
+		errx(EXIT_FAILURE, "gelf_get##REL failed: %s",		\
+		    elf_errmsg(-1));					\
+	REL.r_info = GELF_R_INFO(ecp->symndx[GELF_R_SYM(REL.r_info)],	\
+	    GELF_R_TYPE(REL.r_info));					\
+	if (!gelf_update_##REL(od, i, &REL))				\
+		errx(EXIT_FAILURE, "gelf_update_##REL failed: %s",	\
+		    elf_errmsg(-1));					\
+} while(0)
+
+	if (s->sz == 0)
+		return;
+	if (gelf_getshdr(s->os, &osh) == NULL)
+		errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
+		    elf_errmsg(-1));
+	/* Only process .symtab reloc info. */
+	if (osh.sh_link != elf_ndxscn(ecp->symtab->is))
+		return;
+	if ((od = elf_getdata(s->os, NULL)) == NULL)
+		errx(EXIT_FAILURE, "elf_getdata() failed: %s",
+		    elf_errmsg(-1));
+	n = osh.sh_size / osh.sh_entsize;
+	for(i = 0; (uint64_t)i < n; i++) {
+		if (s->type == SHT_REL)
+			UPDATEREL(rel);
+		else
+			UPDATEREL(rela);
+	}
+}
+
+static void
+pad_section(struct elfcopy *ecp, struct section *s)
+{
+	GElf_Shdr	 osh;
+	Elf_Data	*od;
+
+	if (s == NULL || s->pad_sz == 0)
+		return;
+
+	if ((s->pad = malloc(s->pad_sz)) == NULL)
+		err(EXIT_FAILURE, "malloc failed");
+	memset(s->pad, ecp->fill, s->pad_sz);
+
+	/* Create a new Elf_Data to contain the padding bytes. */
+	if ((od = elf_newdata(s->os)) == NULL)
+		errx(EXIT_FAILURE, "elf_newdata() failed: %s",
+		    elf_errmsg(-1));
+	od->d_align = 1;
+	od->d_off = s->sz;
+	od->d_buf = s->pad;
+	od->d_type = ELF_T_BYTE;
+	od->d_size = s->pad_sz;
+	od->d_version = EV_CURRENT;
+
+	/* Update section header. */
+	if (gelf_getshdr(s->os, &osh) == NULL)
+		errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
+		    elf_errmsg(-1));
+	osh.sh_size = s->sz + s->pad_sz;
+	if (!gelf_update_shdr(s->os, &osh))
+		errx(EXIT_FAILURE, "elf_update_shdr failed: %s",
+		    elf_errmsg(-1));
+}
+
+void
+resync_sections(struct elfcopy *ecp)
+{
+	struct section	*s, *ps;
+	GElf_Shdr	 osh;
+	uint64_t	 off;
+	int		 first;
+
+	ps = NULL;
+	first = 1;
+	off = 0;
+	TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
+		if (first) {
+			off = s->off;
+			first = 0;
+		}
+
+		/*
+		 * Ignore TLS sections with load address 0 and without
+		 * content. We don't need to adjust their file offset or
+		 * VMA, only the size matters.
+		 */
+		if (s->seg_tls != NULL && s->type == SHT_NOBITS &&
+		    s->off == 0)
+			continue;
+
+		/* Align section offset. */
+		if (s->align == 0)
+			s->align = 1;
+		if (off <= s->off) {
+			if (!s->loadable || (ecp->flags & RELOCATABLE))
+				s->off = roundup(off, s->align);
+		} else {
+			if (s->loadable && (ecp->flags & RELOCATABLE) == 0)
+				warnx("moving loadable section %s, "
+				    "is this intentional?", s->name);
+			s->off = roundup(off, s->align);
+		}
+
+		/* Calculate next section offset. */
+		off = s->off;
+		if (s->pseudo || (s->type != SHT_NOBITS && s->type != SHT_NULL))
+			off += s->sz;
+
+		if (s->pseudo) {
+			ps = NULL;
+			continue;
+		}
+
+		/* Count padding bytes added through --pad-to. */
+		if (s->pad_sz > 0)
+			off += s->pad_sz;
+
+		/* Update section header accordingly. */
+		if (gelf_getshdr(s->os, &osh) == NULL)
+			errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
+			    elf_errmsg(-1));
+		osh.sh_addr = s->vma;
+		osh.sh_offset = s->off;
+		osh.sh_size = s->sz;
+		if (!gelf_update_shdr(s->os, &osh))
+			errx(EXIT_FAILURE, "elf_update_shdr failed: %s",
+			    elf_errmsg(-1));
+
+		/* Add padding for previous section, if need. */
+		if (ps != NULL) {
+			if (ps->pad_sz > 0) {
+				/* Apply padding added by --pad-to. */
+				pad_section(ecp, ps);
+			} else if ((ecp->flags & GAP_FILL) &&
+			    (ps->off + ps->sz < s->off)) {
+				/*
+				 * Fill the gap between sections by padding
+				 * the section with lower address.
+				 */
+				ps->pad_sz = s->off - (ps->off + ps->sz);
+				pad_section(ecp, ps);
+			}
+		}
+
+		ps = s;
+	}
+
+	/* Pad the last section, if need. */
+	if (ps != NULL && ps->pad_sz > 0)
+		pad_section(ecp, ps);
+}
+
+static void
+modify_section(struct elfcopy *ecp, struct section *s)
+{
+	struct sec_action	*sac;
+	size_t			 srcsz, dstsz, p, len;
+	char			*b, *c, *d, *src, *end;
+	int			 dupe;
+
+	src = read_section(s, &srcsz);
+	if (src == NULL || srcsz == 0) {
+		/* For empty section, we proceed if we need to append. */
+		if (!is_append_section(ecp, s->name))
+			return;
+	}
+
+	/* Allocate buffer needed for new section data. */
+	dstsz = srcsz;
+	if (is_append_section(ecp, s->name)) {
+		sac = lookup_sec_act(ecp, s->name, 0);
+		dstsz += strlen(sac->string) + 1;
+	}
+	if ((b = malloc(dstsz)) == NULL)
+		err(EXIT_FAILURE, "malloc failed");
+	s->buf = b;
+
+	/* Compress section. */
+	p = 0;
+	if (is_compress_section(ecp, s->name)) {
+		end = src + srcsz;
+		for(c = src; c < end;) {
+			len = 0;
+			while(c + len < end && c[len] != '\0')
+				len++;
+			if (c + len == end) {
+				/* XXX should we warn here? */
+				strncpy(&b[p], c, len);
+				p += len;
+				break;
+			}
+			dupe = 0;
+			for (d = b; d < b + p; ) {
+				if (strcmp(d, c) == 0) {
+					dupe = 1;
+					break;
+				}
+				d += strlen(d) + 1;
+			}
+			if (!dupe) {
+				strncpy(&b[p], c, len);
+				b[p + len] = '\0';
+				p += len + 1;
+			}
+			c += len + 1;
+		}
+	} else {
+		memcpy(b, src, srcsz);
+		p += srcsz;
+	}
+
+	/* Append section. */
+	if (is_append_section(ecp, s->name)) {
+		sac = lookup_sec_act(ecp, s->name, 0);
+		len = strlen(sac->string);
+		strncpy(&b[p], sac->string, len);
+		b[p + len] = '\0';
+		p += len + 1;
+	}
+
+	s->sz = p;
+	s->nocopy = 1;
+}
+
+static void
+print_data(const char *d, size_t sz)
+{
+	const char *c;
+
+	for (c = d; c < d + sz; c++) {
+		if (*c == '\0')
+			putchar('\n');
+		else
+			putchar(*c);
+	}
+}
+
+static void
+print_section(struct section *s)
+{
+	Elf_Data	*id;
+	int		 elferr;
+
+	if (s->buf != NULL && s->sz > 0) {
+		print_data(s->buf, s->sz);
+	} else {
+		id = NULL;
+		while ((id = elf_getdata(s->is, id)) != NULL ||
+		    (id = elf_rawdata(s->is, id)) != NULL) {
+			(void) elf_errno();
+			print_data(id->d_buf, id->d_size);
+		}
+		elferr = elf_errno();
+		if (elferr != 0)
+			errx(EXIT_FAILURE, "elf_getdata() failed: %s",
+			    elf_errmsg(elferr));
+	}
+	putchar('\n');
+}
+
+static void *
+read_section(struct section *s, size_t *size)
+{
+	Elf_Data	*id;
+	char		*b;
+	size_t		 sz;
+	int		 elferr;
+
+	sz = 0;
+	b = NULL;
+	id = NULL;
+	while ((id = elf_getdata(s->is, id)) != NULL ||
+	    (id = elf_rawdata(s->is, id)) != NULL) {
+		(void) elf_errno();
+		if (b == NULL)
+			b = malloc(id->d_size);
+		else
+			b = malloc(sz + id->d_size);
+		if (b == NULL)
+			err(EXIT_FAILURE, "malloc or realloc failed");
+
+		memcpy(&b[sz], id->d_buf, id->d_size);
+		sz += id->d_size;
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		errx(EXIT_FAILURE, "elf_getdata() failed: %s",
+		    elf_errmsg(elferr));
+
+	*size = sz;
+
+	return (b);
+}
+
+void
+copy_shdr(struct elfcopy *ecp, struct section *s, const char *name, int copy,
+    int sec_flags)
+{
+	GElf_Shdr ish, osh;
+
+	if (gelf_getshdr(s->is, &ish) == NULL)
+		errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
+		    elf_errmsg(-1));
+	if (gelf_getshdr(s->os, &osh) == NULL)
+		errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
+		    elf_errmsg(-1));
+
+	if (copy)
+		(void) memcpy(&osh, &ish, sizeof(ish));
+	else {
+		osh.sh_type		= s->type;
+		osh.sh_addr		= s->vma;
+		osh.sh_offset		= s->off;
+		osh.sh_size		= s->sz;
+		osh.sh_link		= ish.sh_link;
+		osh.sh_info		= ish.sh_info;
+		osh.sh_addralign	= s->align;
+		osh.sh_entsize		= ish.sh_entsize;
+
+		if (sec_flags) {
+			osh.sh_flags = 0;
+			if (sec_flags & SF_ALLOC)
+				osh.sh_flags |= SHF_ALLOC;
+			if ((sec_flags & SF_READONLY) == 0)
+				osh.sh_flags |= SHF_WRITE;
+			if (sec_flags & SF_CODE)
+				osh.sh_flags |= SHF_EXECINSTR;
+			if ((sec_flags & SF_CONTENTS) &&
+			    s->type == SHT_NOBITS && s->sz > 0) {
+				/*
+				 * Convert SHT_NOBITS section to section with
+				 * (zero'ed) content on file.
+				 */
+				osh.sh_type = s->type = SHT_PROGBITS;
+				if ((s->buf = calloc(1, s->sz)) == NULL)
+					err(EXIT_FAILURE, "malloc failed");
+				s->nocopy = 1;
+			}
+		} else {
+			osh.sh_flags = ish.sh_flags;
+			/*
+			 * Newer binutils as(1) emits the section flag
+			 * SHF_INFO_LINK for relocation sections. elfcopy
+			 * emits this flag in the output section if it's
+			 * missing in the input section, to remain compatible
+			 * with binutils.
+			 */
+			if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA)
+				osh.sh_flags |= SHF_INFO_LINK;
+		}
+	}
+
+	if (name == NULL)
+		add_to_shstrtab(ecp, s->name);
+	else
+		add_to_shstrtab(ecp, name);
+
+	if (!gelf_update_shdr(s->os, &osh))
+		errx(EXIT_FAILURE, "elf_update_shdr failed: %s",
+		    elf_errmsg(-1));
+}
+
+void
+copy_data(struct section *s)
+{
+	Elf_Data	*id, *od;
+	int		 elferr;
+
+	if (s->nocopy && s->buf == NULL)
+		return;
+
+	if ((id = elf_getdata(s->is, NULL)) == NULL) {
+		(void) elf_errno();
+		if ((id = elf_rawdata(s->is, NULL)) == NULL) {
+			elferr = elf_errno();
+			if (elferr != 0)
+				errx(EXIT_FAILURE, "failed to read section:"
+				    " %s", s->name);
+			return;
+		}
+	}
+
+	if ((od = elf_newdata(s->os)) == NULL)
+		errx(EXIT_FAILURE, "elf_newdata() failed: %s",
+		    elf_errmsg(-1));
+
+	if (s->nocopy) {
+		/* Use s->buf as content if s->nocopy is set. */
+		od->d_align	= id->d_align;
+		od->d_off	= 0;
+		od->d_buf	= s->buf;
+		od->d_type	= id->d_type;
+		od->d_size	= s->sz;
+		od->d_version	= id->d_version;
+	} else {
+		od->d_align	= id->d_align;
+		od->d_off	= id->d_off;
+		od->d_buf	= id->d_buf;
+		od->d_type	= id->d_type;
+		od->d_size	= id->d_size;
+		od->d_version	= id->d_version;
+	}
+
+	/*
+	 * Alignment Fixup. libelf does not allow the alignment for
+	 * Elf_Data descriptor to be set to 0. In this case we workaround
+	 * it by setting the alignment to 1.
+	 *
+	 * According to the ELF ABI, alignment 0 and 1 has the same
+	 * meaning: the section has no alignment constraints.
+	 */
+	if (od->d_align == 0)
+		od->d_align = 1;
+}
+
+struct section *
+create_external_section(struct elfcopy *ecp, const char *name, char *newname,
+    void *buf, uint64_t size, uint64_t off, uint64_t stype, Elf_Type dtype,
+    uint64_t flags, uint64_t align, uint64_t vma, int loadable)
+{
+	struct section	*s;
+	Elf_Scn		*os;
+	Elf_Data	*od;
+	GElf_Shdr	 osh;
+
+	if ((os = elf_newscn(ecp->eout)) == NULL)
+		errx(EXIT_FAILURE, "elf_newscn() failed: %s",
+		    elf_errmsg(-1));
+	if ((s = calloc(1, sizeof(*s))) == NULL)
+		err(EXIT_FAILURE, "calloc failed");
+	s->name = name;
+	s->newname = newname;	/* needs to be free()'ed */
+	s->off = off;
+	s->sz = size;
+	s->vma = vma;
+	s->align = align;
+	s->loadable = loadable;
+	s->is = NULL;
+	s->os = os;
+	s->type = stype;
+	s->nocopy = 1;
+	insert_to_sec_list(ecp, s, 1);
+
+	if (gelf_getshdr(os, &osh) == NULL)
+		errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
+		    elf_errmsg(-1));
+	osh.sh_flags = flags;
+	osh.sh_type = s->type;
+	osh.sh_addr = s->vma;
+	osh.sh_addralign = s->align;
+	if (!gelf_update_shdr(os, &osh))
+		errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s",
+		    elf_errmsg(-1));
+	add_to_shstrtab(ecp, name);
+
+	if (buf != NULL && size != 0) {
+		if ((od = elf_newdata(os)) == NULL)
+			errx(EXIT_FAILURE, "elf_newdata() failed: %s",
+			    elf_errmsg(-1));
+		od->d_align = align;
+		od->d_off = 0;
+		od->d_buf = buf;
+		od->d_size = size;
+		od->d_type = dtype;
+		od->d_version = EV_CURRENT;
+	}
+
+	/*
+	 * Clear SYMTAB_INTACT, as we probably need to update/add new
+	 * STT_SECTION symbols into the symbol table.
+	 */
+	ecp->flags &= ~SYMTAB_INTACT;
+
+	return (s);
+}
+
+/*
+ * Insert sections specified by --add-section to the end of section list.
+ */
+static void
+insert_sections(struct elfcopy *ecp)
+{
+	struct sec_add	*sa;
+	struct section	*s;
+	size_t		 off;
+	uint64_t	 stype;
+
+	/* Put these sections in the end of current list. */
+	off = 0;
+	TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
+		if (s->type != SHT_NOBITS && s->type != SHT_NULL)
+			off = s->off + s->sz;
+		else
+			off = s->off;
+	}
+
+	STAILQ_FOREACH(sa, &ecp->v_sadd, sadd_list) {
+
+		/* TODO: Add section header vma/lma, flag changes here */
+
+		/*
+		 * The default section type for user added section is
+		 * SHT_PROGBITS. If the section name match certain patterns,
+		 * elfcopy will try to set a more appropriate section type.
+		 * However, data type is always set to ELF_T_BYTE and no
+		 * translation is performed by libelf.
+		 */
+		stype = SHT_PROGBITS;
+		if (strcmp(sa->name, ".note") == 0 ||
+		    strncmp(sa->name, ".note.", strlen(".note.")) == 0)
+			stype = SHT_NOTE;
+
+		(void) create_external_section(ecp, sa->name, NULL, sa->content,
+		    sa->size, off, stype, ELF_T_BYTE, 0, 1, 0, 0);
+	}
+}
+
+void
+add_to_shstrtab(struct elfcopy *ecp, const char *name)
+{
+	struct section *s;
+
+	s = ecp->shstrtab;
+	insert_to_strtab(s, name);
+}
+
+void
+update_shdr(struct elfcopy *ecp, int update_link)
+{
+	struct section	*s;
+	GElf_Shdr	 osh;
+	int		 elferr;
+
+	TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
+		if (s->pseudo)
+			continue;
+
+		if (gelf_getshdr(s->os, &osh) == NULL)
+			errx(EXIT_FAILURE, "gelf_getshdr failed: %s",
+			    elf_errmsg(-1));
+
+		/* Find section name in string table and set sh_name. */
+		osh.sh_name = lookup_string(ecp->shstrtab, s->name);
+
+		/*
+		 * sh_link needs to be updated, since the index of the
+		 * linked section might have changed.
+		 */
+		if (update_link && osh.sh_link != 0)
+			osh.sh_link = ecp->secndx[osh.sh_link];
+
+		/*
+		 * sh_info of relocation section links to the section to which
+		 * its relocation info applies. So it may need update as well.
+		 */
+		if ((s->type == SHT_REL || s->type == SHT_RELA) &&
+		    osh.sh_info != 0)
+			osh.sh_info = ecp->secndx[osh.sh_info];
+
+		/*
+		 * sh_info of SHT_GROUP section needs to point to the correct
+		 * string in the symbol table.
+		 */
+		if (s->type == SHT_GROUP && (ecp->flags & SYMTAB_EXIST) &&
+		    (ecp->flags & SYMTAB_INTACT) == 0)
+			osh.sh_info = ecp->symndx[osh.sh_info];
+
+		if (!gelf_update_shdr(s->os, &osh))
+			errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s",
+			    elf_errmsg(-1));
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		errx(EXIT_FAILURE, "elf_nextscn failed: %s",
+		    elf_errmsg(elferr));
+}
+
+void
+init_shstrtab(struct elfcopy *ecp)
+{
+	struct section *s;
+
+	if ((ecp->shstrtab = calloc(1, sizeof(*ecp->shstrtab))) == NULL)
+		err(EXIT_FAILURE, "calloc failed");
+	s = ecp->shstrtab;
+	s->name = ".shstrtab";
+	s->is = NULL;
+	s->sz = 0;
+	s->align = 1;
+	s->loadable = 0;
+	s->type = SHT_STRTAB;
+	s->vma = 0;
+
+	insert_to_strtab(s, "");
+	insert_to_strtab(s, ".symtab");
+	insert_to_strtab(s, ".strtab");
+	insert_to_strtab(s, ".shstrtab");
+}
+
+void
+set_shstrtab(struct elfcopy *ecp)
+{
+	struct section	*s;
+	Elf_Data	*data;
+	GElf_Shdr	 sh;
+
+	s = ecp->shstrtab;
+
+	if (s->os == NULL) {
+		/* Input object does not contain .shstrtab section */
+		if ((s->os = elf_newscn(ecp->eout)) == NULL)
+			errx(EXIT_FAILURE, "elf_newscn failed: %s",
+			    elf_errmsg(-1));
+		insert_to_sec_list(ecp, s, 1);
+	}
+
+	if (gelf_getshdr(s->os, &sh) == NULL)
+		errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
+		    elf_errmsg(-1));
+	sh.sh_addr	= 0;
+	sh.sh_addralign	= 1;
+	sh.sh_offset	= s->off;
+	sh.sh_type	= SHT_STRTAB;
+	sh.sh_flags	= 0;
+	sh.sh_entsize	= 0;
+	sh.sh_info	= 0;
+	sh.sh_link	= 0;
+
+	if ((data = elf_newdata(s->os)) == NULL)
+		errx(EXIT_FAILURE, "elf_newdata() failed: %s",
+		    elf_errmsg(-1));
+
+	/*
+	 * If we don't have a symbol table, skip those a few bytes
+	 * which are reserved for this in the beginning of shstrtab.
+	 */
+	if (!(ecp->flags & SYMTAB_EXIST)) {
+		s->sz -= sizeof(".symtab\0.strtab");
+		memmove(s->buf, (char *)s->buf + sizeof(".symtab\0.strtab"),
+		    s->sz);
+	}
+
+	sh.sh_size	= s->sz;
+	if (!gelf_update_shdr(s->os, &sh))
+		errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s",
+		    elf_errmsg(-1));
+
+	data->d_align	= 1;
+	data->d_buf	= s->buf;
+	data->d_size	= s->sz;
+	data->d_off	= 0;
+	data->d_type	= ELF_T_BYTE;
+	data->d_version	= EV_CURRENT;
+
+	if (!elf_setshstrndx(ecp->eout, elf_ndxscn(s->os)))
+		errx(EXIT_FAILURE, "elf_setshstrndx() failed: %s",
+		     elf_errmsg(-1));
+}
+
+void
+add_section(struct elfcopy *ecp, const char *arg)
+{
+	struct sec_add	*sa;
+	struct stat	 sb;
+	const char	*s, *fn;
+	FILE		*fp;
+	int		 len;
+
+	if ((s = strchr(arg, '=')) == NULL)
+		errx(EXIT_FAILURE,
+		    "illegal format for --add-section option");
+	if ((sa = malloc(sizeof(*sa))) == NULL)
+		err(EXIT_FAILURE, "malloc failed");
+
+	len = s - arg;
+	if ((sa->name = malloc(len + 1)) == NULL)
+		err(EXIT_FAILURE, "malloc failed");
+	strncpy(sa->name, arg, len);
+	sa->name[len] = '\0';
+
+	fn = s + 1;
+	if (stat(fn, &sb) == -1)
+		err(EXIT_FAILURE, "stat failed");
+	sa->size = sb.st_size;
+	if (sa->size > 0) {
+		if ((sa->content = malloc(sa->size)) == NULL)
+			err(EXIT_FAILURE, "malloc failed");
+		if ((fp = fopen(fn, "r")) == NULL)
+			err(EXIT_FAILURE, "can not open %s", fn);
+		if (fread(sa->content, 1, sa->size, fp) == 0 ||
+		    ferror(fp))
+			err(EXIT_FAILURE, "fread failed");
+		fclose(fp);
+	} else
+		sa->content = NULL;
+
+	STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list);
+	ecp->flags |= SEC_ADD;
+}
+
+void
+free_sec_add(struct elfcopy *ecp)
+{
+	struct sec_add *sa, *sa_temp;
+
+	STAILQ_FOREACH_SAFE(sa, &ecp->v_sadd, sadd_list, sa_temp) {
+		STAILQ_REMOVE(&ecp->v_sadd, sa, sec_add, sadd_list);
+		free(sa->name);
+		free(sa->content);
+		free(sa);
+	}
+}
+
+static void
+add_gnu_debuglink(struct elfcopy *ecp)
+{
+	struct sec_add	*sa;
+	struct stat	 sb;
+	FILE		*fp;
+	char		*fnbase, *buf;
+	int		 crc_off;
+	int		 crc;
+
+	if (ecp->debuglink == NULL)
+		return;
+
+	/* Read debug file content. */
+	if ((sa = malloc(sizeof(*sa))) == NULL)
+		err(EXIT_FAILURE, "malloc failed");
+	if ((sa->name = strdup(".gnu_debuglink")) == NULL)
+		err(EXIT_FAILURE, "strdup failed");
+	if (stat(ecp->debuglink, &sb) == -1)
+		err(EXIT_FAILURE, "stat failed");
+	if (sb.st_size == 0)
+		errx(EXIT_FAILURE, "empty debug link target %s",
+		    ecp->debuglink);
+	if ((buf = malloc(sb.st_size)) == NULL)
+		err(EXIT_FAILURE, "malloc failed");
+	if ((fp = fopen(ecp->debuglink, "r")) == NULL)
+		err(EXIT_FAILURE, "can not open %s", ecp->debuglink);
+	if (fread(buf, 1, sb.st_size, fp) == 0 ||
+	    ferror(fp))
+		err(EXIT_FAILURE, "fread failed");
+	fclose(fp);
+
+	/* Calculate crc checksum.  */
+	crc = calc_crc32(buf, sb.st_size, 0xFFFFFFFF);
+	free(buf);
+
+	/* Calculate section size and the offset to store crc checksum. */
+	if ((fnbase = basename(ecp->debuglink)) == NULL)
+		err(EXIT_FAILURE, "basename failed");
+	crc_off = roundup(strlen(fnbase) + 1, 4);
+	sa->size = crc_off + 4;
+
+	/* Section content. */
+	if ((sa->content = calloc(1, sa->size)) == NULL)
+		err(EXIT_FAILURE, "malloc failed");
+	strncpy(sa->content, fnbase, strlen(fnbase));
+	if (ecp->oed == ELFDATA2LSB) {
+		sa->content[crc_off] = crc & 0xFF;
+		sa->content[crc_off + 1] = (crc >> 8) & 0xFF;
+		sa->content[crc_off + 2] = (crc >> 16) & 0xFF;
+		sa->content[crc_off + 3] = crc >> 24;
+	} else {
+		sa->content[crc_off] = crc >> 24;
+		sa->content[crc_off + 1] = (crc >> 16) & 0xFF;
+		sa->content[crc_off + 2] = (crc >> 8) & 0xFF;
+		sa->content[crc_off + 3] = crc & 0xFF;
+	}
+
+	STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list);
+	ecp->flags |= SEC_ADD;
+}
+
+static void
+insert_to_strtab(struct section *t, const char *s)
+{
+	const char	*r;
+	char		*b, *c;
+	size_t		 len, slen;
+	int		 append;
+
+	if (t->sz == 0) {
+		t->cap = 512;
+		if ((t->buf = malloc(t->cap)) == NULL)
+			err(EXIT_FAILURE, "malloc failed");
+	}
+
+	slen = strlen(s);
+	append = 0;
+	b = t->buf;
+	for (c = b; c < b + t->sz;) {
+		len = strlen(c);
+		if (!append && len >= slen) {
+			r = c + (len - slen);
+			if (strcmp(r, s) == 0)
+				return;
+		} else if (len < slen && len != 0) {
+			r = s + (slen - len);
+			if (strcmp(c, r) == 0) {
+				t->sz -= len + 1;
+				memmove(c, c + len + 1, t->sz - (c - b));
+				append = 1;
+				continue;
+			}
+		}
+		c += len + 1;
+	}
+
+	while (t->sz + slen + 1 >= t->cap) {
+		t->cap *= 2;
+		if ((t->buf = realloc(t->buf, t->cap)) == NULL)
+			err(EXIT_FAILURE, "realloc failed");
+	}
+	b = t->buf;
+	strncpy(&b[t->sz], s, slen);
+	b[t->sz + slen] = '\0';
+	t->sz += slen + 1;
+}
+
+static int
+lookup_string(struct section *t, const char *s)
+{
+	const char	*b, *c, *r;
+	size_t		 len, slen;
+
+	slen = strlen(s);
+	b = t->buf;
+	for (c = b; c < b + t->sz;) {
+		len = strlen(c);
+		if (len >= slen) {
+			r = c + (len - slen);
+			if (strcmp(r, s) == 0)
+				return (r - b);
+		}
+		c += len + 1;
+	}
+
+	return (-1);
+}
+
+static uint32_t crctable[256] =
+{
+	0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL,
+	0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L,
+	0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L,
+	0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L,
+	0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL,
+	0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L,
+	0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL,
+	0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L,
+	0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L,
+	0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL,
+	0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L,
+	0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L,
+	0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L,
+	0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL,
+	0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L,
+	0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL,
+	0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL,
+	0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L,
+	0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L,
+	0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L,
+	0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL,
+	0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L,
+	0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL,
+	0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L,
+	0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L,
+	0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL,
+	0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L,
+	0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L,
+	0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L,
+	0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL,
+	0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L,
+	0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL,
+	0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL,
+	0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L,
+	0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L,
+	0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L,
+	0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL,
+	0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L,
+	0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL,
+	0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L,
+	0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L,
+	0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL,
+	0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L,
+	0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L,
+	0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L,
+	0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL,
+	0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L,
+	0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL,
+	0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL,
+	0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L,
+	0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L,
+	0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L,
+	0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL,
+	0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L,
+	0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL,
+	0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L,
+	0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L,
+	0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL,
+	0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L,
+	0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L,
+	0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L,
+	0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL,
+	0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L,
+	0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL
+};
+
+static uint32_t
+calc_crc32(const char *p, size_t len, uint32_t crc)
+{
+	uint32_t i;
+
+	for (i = 0; i < len; i++) {
+		crc = crctable[(crc ^ *p++) & 0xFFL] ^ (crc >> 8);
+	}
+
+	return (crc ^ 0xFFFFFFFF);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/elfcopy/segments.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,592 @@
+/*-
+ * Copyright (c) 2007-2010,2012 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/queue.h>
+#include <err.h>
+#include <gelf.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "elfcopy.h"
+
+ELFTC_VCSID("$Id: segments.c 3449 2016-05-03 13:59:29Z emaste $");
+
+static void	insert_to_inseg_list(struct segment *seg, struct section *sec);
+
+/*
+ * elfcopy's segment handling is relatively simpler and less powerful than
+ * libbfd. Program headers are modified or copied from input to output objects,
+ * but never re-generated. As a result, if the input object has incorrect
+ * program headers, the output object's program headers will remain incorrect
+ * or become even worse.
+ */
+
+/*
+ * Check whether a section is "loadable". If so, add it to the
+ * corresponding segment list(s) and return 1.
+ */
+int
+add_to_inseg_list(struct elfcopy *ecp, struct section *s)
+{
+	struct segment	*seg;
+	int		 loadable;
+
+	if (ecp->ophnum == 0)
+		return (0);
+
+	/*
+	 * Segment is a different view of an ELF object. One segment can
+	 * contain one or more sections, and one section can be included
+	 * in one or more segments, or not included in any segment at all.
+	 * We call those sections which can be found in one or more segments
+	 * "loadable" sections, and call the rest "unloadable" sections.
+	 * We keep track of "loadable" sections in their containing
+	 * segment(s)' v_sec queue. These information are later used to
+	 * recalculate the extents of segments, when sections are removed,
+	 * for example.
+	 */
+	loadable = 0;
+	STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) {
+		if (s->off < seg->off || (s->vma < seg->vaddr && !s->pseudo))
+			continue;
+		if (s->off + s->sz > seg->off + seg->fsz &&
+		    s->type != SHT_NOBITS)
+			continue;
+		if (s->vma + s->sz > seg->vaddr + seg->msz)
+			continue;
+		if (seg->type == PT_TLS && ((s->flags & SHF_TLS) == 0))
+			continue;
+
+		insert_to_inseg_list(seg, s);
+		if (seg->type == PT_LOAD)
+			s->seg = seg;
+		else if (seg->type == PT_TLS)
+			s->seg_tls = seg;
+		if (s->pseudo)
+			s->vma = seg->vaddr + (s->off - seg->off);
+		if (seg->paddr > 0)
+			s->lma = seg->paddr + (s->off - seg->off);
+		else
+			s->lma = 0;
+		loadable = 1;
+	}
+
+	return (loadable);
+}
+
+void
+adjust_addr(struct elfcopy *ecp)
+{
+	struct section *s, *s0;
+	struct segment *seg;
+	struct sec_action *sac;
+	uint64_t dl, vma, lma, start, end;
+	int found, i;
+
+	/*
+	 * Apply VMA and global LMA changes in the first iteration.
+	 */
+	TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
+
+		/* Only adjust loadable section's address. */
+		if (!s->loadable)
+			continue;
+
+		/* Apply global VMA adjustment. */
+		if (ecp->change_addr != 0)
+			s->vma += ecp->change_addr;
+
+		/* Apply global LMA adjustment. */
+		if (ecp->change_addr != 0 && s->seg != NULL &&
+		    s->seg->paddr > 0)
+			s->lma += ecp->change_addr;
+	}
+
+	/*
+	 * Apply sections VMA change in the second iteration.
+	 */
+	TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
+
+		if (!s->loadable)
+			continue;
+
+		/*
+		 * Check if there is a VMA change request for this
+		 * section.
+		 */
+		sac = lookup_sec_act(ecp, s->name, 0);
+		if (sac == NULL)
+			continue;
+		vma = s->vma;
+		if (sac->setvma)
+			vma = sac->vma;
+		if (sac->vma_adjust != 0)
+			vma += sac->vma_adjust;
+		if (vma == s->vma)
+			continue;
+
+		/*
+		 * No need to make segment adjustment if the section doesn't
+		 * belong to any segment.
+		 */
+		if (s->seg == NULL) {
+			s->vma = vma;
+			continue;
+		}
+
+		/*
+		 * Check if the VMA change is viable.
+		 *
+		 * 1. Check if the new VMA is properly aligned accroding to
+		 *    section alignment.
+		 *
+		 * 2. Compute the new extent of segment that contains this
+		 *    section, make sure it doesn't overlap with other
+		 *    segments.
+		 */
+#ifdef	DEBUG
+		printf("VMA for section %s: %#jx\n", s->name, vma);
+#endif
+
+		if (vma % s->align != 0)
+			errx(EXIT_FAILURE, "The VMA %#jx for "
+			    "section %s is not aligned to %ju",
+			    (uintmax_t) vma, s->name, (uintmax_t) s->align);
+
+		if (vma < s->vma) {
+			/* Move section to lower address. */
+			if (vma < s->vma - s->seg->vaddr)
+				errx(EXIT_FAILURE, "Not enough space to move "
+				    "section %s VMA to %#jx", s->name,
+				    (uintmax_t) vma);
+			start = vma - (s->vma - s->seg->vaddr);
+			if (s == s->seg->v_sec[s->seg->nsec - 1])
+				end = start + s->seg->msz;
+			else
+				end = s->seg->vaddr + s->seg->msz;
+		} else {
+			/* Move section to upper address. */
+			if (s == s->seg->v_sec[0])
+				start = vma;
+			else
+				start = s->seg->vaddr;
+			end = vma + (s->seg->vaddr + s->seg->msz - s->vma);
+			if (end < start)
+				errx(EXIT_FAILURE, "Not enough space to move "
+				    "section %s VMA to %#jx", s->name,
+				    (uintmax_t) vma);
+		}
+
+#ifdef	DEBUG
+		printf("new extent for segment containing %s: (%#jx,%#jx)\n",
+		    s->name, start, end);
+#endif
+
+		STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) {
+			if (seg == s->seg || seg->type != PT_LOAD)
+				continue;
+			if (start > seg->vaddr + seg->msz)
+				continue;
+			if (end < seg->vaddr)
+				continue;
+			errx(EXIT_FAILURE, "The extent of segment containing "
+			    "section %s overlaps with segment(%#jx,%#jx)",
+			    s->name, (uintmax_t) seg->vaddr,
+			    (uintmax_t) (seg->vaddr + seg->msz));
+		}
+
+		/*
+		 * Update section VMA and file offset.
+		 */
+
+		if (vma < s->vma) {
+			/*
+			 * To move a section to lower VMA, we decrease
+			 * the VMA of the section and all the sections that
+			 * are before it, and we increase the file offsets
+			 * of all the sections that are after it.
+			 */
+			dl = s->vma - vma;
+			for (i = 0; i < s->seg->nsec; i++) {
+				s0 = s->seg->v_sec[i];
+				s0->vma -= dl;
+#ifdef	DEBUG
+				printf("section %s VMA set to %#jx\n",
+				    s0->name, (uintmax_t) s0->vma);
+#endif
+				if (s0 == s)
+					break;
+			}
+			for (i = i + 1; i < s->seg->nsec; i++) {
+				s0 = s->seg->v_sec[i];
+				s0->off += dl;
+#ifdef	DEBUG
+				printf("section %s offset set to %#jx\n",
+				    s0->name, (uintmax_t) s0->off);
+#endif
+			}
+		} else {
+			/*
+			 * To move a section to upper VMA, we increase
+			 * the VMA of the section and all the sections that
+			 * are after it, and we increase the their file
+			 * offsets too unless the section in question
+			 * is the first in its containing segment.
+			 */
+			dl = vma - s->vma;
+			for (i = 0; i < s->seg->nsec; i++)
+				if (s->seg->v_sec[i] == s)
+					break;
+			if (i >= s->seg->nsec)
+				errx(EXIT_FAILURE, "Internal: section `%s' not"
+				    " found in its containing segement",
+				    s->name);
+			for (; i < s->seg->nsec; i++) {
+				s0 = s->seg->v_sec[i];
+				s0->vma += dl;
+#ifdef	DEBUG
+				printf("section %s VMA set to %#jx\n",
+				    s0->name, (uintmax_t) s0->lma);
+#endif
+				if (s != s->seg->v_sec[0]) {
+					s0->off += dl;
+#ifdef	DEBUG
+					printf("section %s offset set to %#jx\n",
+					    s0->name, (uintmax_t) s0->off);
+#endif
+				}
+			}
+		}
+	}
+
+	/*
+	 * Apply load address padding.
+	 */
+
+	if (ecp->pad_to != 0) {
+
+		/*
+		 * Find the section with highest VMA.
+		 */
+		s = NULL;
+		STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) {
+			if (seg->type != PT_LOAD)
+				continue;
+			for (i = seg->nsec - 1; i >= 0; i--)
+				if (seg->v_sec[i]->type != SHT_NOBITS)
+					break;
+			if (i < 0)
+				continue;
+			if (s == NULL)
+				s = seg->v_sec[i];
+			else {
+				s0 = seg->v_sec[i];
+				if (s0->vma > s->vma)
+					s = s0;
+			}
+		}
+
+		if (s == NULL)
+			goto adjust_lma;
+
+		/* No need to pad if the pad_to address is lower. */
+		if (ecp->pad_to <= s->vma + s->sz)
+			goto adjust_lma;
+
+		s->pad_sz = ecp->pad_to - (s->vma + s->sz);
+#ifdef	DEBUG
+		printf("pad section %s VMA to address %#jx by %#jx\n", s->name,
+		    (uintmax_t) ecp->pad_to, (uintmax_t) s->pad_sz);
+#endif
+	}
+
+
+adjust_lma:
+
+	/*
+	 * Apply sections LMA change in the third iteration.
+	 */
+	TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
+
+		/*
+		 * Only loadable section that's inside a segment can have
+		 * LMA adjusted. Also, if LMA of the containing segment is
+		 * set to 0, it probably means we should ignore the LMA.
+		 */
+		if (!s->loadable || s->seg == NULL || s->seg->paddr == 0)
+			continue;
+
+		/*
+		 * Check if there is a LMA change request for this
+		 * section.
+		 */
+		sac = lookup_sec_act(ecp, s->name, 0);
+		if (sac == NULL)
+			continue;
+		if (!sac->setlma && sac->lma_adjust == 0)
+			continue;
+		lma = s->lma;
+		if (sac->setlma)
+			lma = sac->lma;
+		if (sac->lma_adjust != 0)
+			lma += sac->lma_adjust;
+		if (lma == s->lma)
+			continue;
+
+#ifdef	DEBUG
+		printf("LMA for section %s: %#jx\n", s->name, lma);
+#endif
+
+		/* Check alignment. */
+		if (lma % s->align != 0)
+			errx(EXIT_FAILURE, "The LMA %#jx for "
+			    "section %s is not aligned to %ju",
+			    (uintmax_t) lma, s->name, (uintmax_t) s->align);
+
+		/*
+		 * Update section LMA.
+		 */
+
+		if (lma < s->lma) {
+			/*
+			 * To move a section to lower LMA, we decrease
+			 * the LMA of the section and all the sections that
+			 * are before it.
+			 */
+			dl = s->lma - lma;
+			for (i = 0; i < s->seg->nsec; i++) {
+				s0 = s->seg->v_sec[i];
+				s0->lma -= dl;
+#ifdef	DEBUG
+				printf("section %s LMA set to %#jx\n",
+				    s0->name, (uintmax_t) s0->lma);
+#endif
+				if (s0 == s)
+					break;
+			}
+		} else {
+			/*
+			 * To move a section to upper LMA, we increase
+			 * the LMA of the section and all the sections that
+			 * are after it.
+			 */
+			dl = lma - s->lma;
+			for (i = 0; i < s->seg->nsec; i++)
+				if (s->seg->v_sec[i] == s)
+					break;
+			if (i >= s->seg->nsec)
+				errx(EXIT_FAILURE, "Internal: section `%s' not"
+				    " found in its containing segement",
+				    s->name);
+			for (; i < s->seg->nsec; i++) {
+				s0 = s->seg->v_sec[i];
+				s0->lma += dl;
+#ifdef	DEBUG
+				printf("section %s LMA set to %#jx\n",
+				    s0->name, (uintmax_t) s0->lma);
+#endif
+			}
+		}
+	}
+
+	/*
+	 * Issue a warning if there are VMA/LMA adjust requests for
+	 * some nonexistent sections.
+	 */
+	if ((ecp->flags & NO_CHANGE_WARN) == 0) {
+		STAILQ_FOREACH(sac, &ecp->v_sac, sac_list) {
+			if (!sac->setvma && !sac->setlma &&
+			    !sac->vma_adjust && !sac->lma_adjust)
+				continue;
+			found = 0;
+			TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
+				if (s->pseudo || s->name == NULL)
+					continue;
+				if (!strcmp(s->name, sac->name)) {
+					found = 1;
+					break;
+				}
+			}
+			if (!found)
+				warnx("cannot find section `%s'", sac->name);
+		}
+	}
+}
+
+static void
+insert_to_inseg_list(struct segment *seg, struct section *sec)
+{
+	struct section *s;
+	int i;
+
+	seg->nsec++;
+	seg->v_sec = realloc(seg->v_sec, seg->nsec * sizeof(*seg->v_sec));
+	if (seg->v_sec == NULL)
+		err(EXIT_FAILURE, "realloc failed");
+
+	/*
+	 * Sort the section in order of offset.
+	 */
+
+	for (i = seg->nsec - 1; i > 0; i--) {
+		s = seg->v_sec[i - 1];
+		if (sec->off >= s->off) {
+			seg->v_sec[i] = sec;
+			break;
+		} else
+			seg->v_sec[i] = s;
+	}
+	if (i == 0)
+		seg->v_sec[0] = sec;
+}
+
+void
+setup_phdr(struct elfcopy *ecp)
+{
+	struct segment	*seg;
+	GElf_Phdr	 iphdr;
+	size_t		 iphnum, i;
+
+	if (elf_getphnum(ecp->ein, &iphnum) == 0)
+		errx(EXIT_FAILURE, "elf_getphnum failed: %s",
+		    elf_errmsg(-1));
+
+	ecp->ophnum = ecp->iphnum = iphnum;
+	if (iphnum == 0)
+		return;
+
+	/* If --only-keep-debug is specified, discard all program headers. */
+	if (ecp->strip == STRIP_NONDEBUG) {
+		ecp->ophnum = 0;
+		return;
+	}
+
+	for (i = 0; i < iphnum; i++) {
+		if (gelf_getphdr(ecp->ein, i, &iphdr) != &iphdr)
+			errx(EXIT_FAILURE, "gelf_getphdr failed: %s",
+			    elf_errmsg(-1));
+		if ((seg = calloc(1, sizeof(*seg))) == NULL)
+			err(EXIT_FAILURE, "calloc failed");
+		seg->vaddr	= iphdr.p_vaddr;
+		seg->paddr	= iphdr.p_paddr;
+		seg->off	= iphdr.p_offset;
+		seg->fsz	= iphdr.p_filesz;
+		seg->msz	= iphdr.p_memsz;
+		seg->type	= iphdr.p_type;
+		STAILQ_INSERT_TAIL(&ecp->v_seg, seg, seg_list);
+	}
+}
+
+void
+copy_phdr(struct elfcopy *ecp)
+{
+	struct segment	*seg;
+	struct section	*s;
+	GElf_Phdr	 iphdr, ophdr;
+	int		 i;
+
+	STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) {
+		if (seg->type == PT_PHDR) {
+			if (!TAILQ_EMPTY(&ecp->v_sec)) {
+				s = TAILQ_FIRST(&ecp->v_sec);
+				if (s->pseudo) {
+					seg->vaddr = s->vma +
+					    gelf_fsize(ecp->eout, ELF_T_EHDR,
+						1, EV_CURRENT);
+					seg->paddr = s->lma +
+					    gelf_fsize(ecp->eout, ELF_T_EHDR,
+						1, EV_CURRENT);
+				}
+			}
+			seg->fsz = seg->msz = gelf_fsize(ecp->eout, ELF_T_PHDR,
+			    ecp->ophnum, EV_CURRENT);
+			continue;
+		}
+
+		if (seg->nsec > 0) {
+			s = seg->v_sec[0];
+			seg->vaddr = s->vma;
+			seg->paddr = s->lma;
+		}
+
+		seg->fsz = seg->msz = 0;
+		for (i = 0; i < seg->nsec; i++) {
+			s = seg->v_sec[i];
+			seg->msz = s->vma + s->sz - seg->vaddr;
+			if (s->type != SHT_NOBITS)
+				seg->fsz = s->off + s->sz - seg->off;
+		}
+	}
+
+	/*
+	 * Allocate space for program headers, note that libelf keep
+	 * track of the number in internal variable, and a call to
+	 * elf_update is needed to update e_phnum of ehdr.
+	 */
+	if (gelf_newphdr(ecp->eout, ecp->ophnum) == NULL)
+		errx(EXIT_FAILURE, "gelf_newphdr() failed: %s",
+		    elf_errmsg(-1));
+
+	/*
+	 * This elf_update() call is to update the e_phnum field in
+	 * ehdr. It's necessary because later we will call gelf_getphdr(),
+	 * which does sanity check by comparing ndx argument with e_phnum.
+	 */
+	if (elf_update(ecp->eout, ELF_C_NULL) < 0)
+		errx(EXIT_FAILURE, "elf_update() failed: %s", elf_errmsg(-1));
+
+	/*
+	 * iphnum == ophnum, since we don't remove program headers even if
+	 * they no longer contain sections.
+	 */
+	i = 0;
+	STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) {
+		if (i >= ecp->iphnum)
+			break;
+		if (gelf_getphdr(ecp->ein, i, &iphdr) != &iphdr)
+			errx(EXIT_FAILURE, "gelf_getphdr failed: %s",
+			    elf_errmsg(-1));
+		if (gelf_getphdr(ecp->eout, i, &ophdr) != &ophdr)
+			errx(EXIT_FAILURE, "gelf_getphdr failed: %s",
+			    elf_errmsg(-1));
+
+		ophdr.p_type = iphdr.p_type;
+		ophdr.p_vaddr = seg->vaddr;
+		ophdr.p_paddr = seg->paddr;
+		ophdr.p_flags = iphdr.p_flags;
+		ophdr.p_align = iphdr.p_align;
+		ophdr.p_offset = seg->off;
+		ophdr.p_filesz = seg->fsz;
+		ophdr.p_memsz = seg->msz;
+		if (!gelf_update_phdr(ecp->eout, i, &ophdr))
+			errx(EXIT_FAILURE, "gelf_update_phdr failed: %s",
+			    elf_errmsg(-1));
+
+		i++;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/elfcopy/strip.1	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,132 @@
+.\" Copyright (c) 2011 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY JOSEPH KOSHY ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL JOSEPH KOSHY BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: strip.1 2069 2011-10-26 15:53:48Z jkoshy $
+.\"
+.Dd September 17, 2011
+.Os
+.Dt STRIP 1
+.Sh NAME
+.Nm strip
+.Nd discard information from ELF objects
+.Sh SYNOPSIS
+.Nm
+.Op Fl d | Fl g | Fl S | Fl -strip-debug
+.Op Fl h | Fl -help
+.Op Fl -only-keep-debug
+.Op Fl o Ar outputfile | Fl -output-file= Ns Ar outputfile
+.Op Fl p | Fl -preserve-dates
+.Op Fl s | Fl -strip-all
+.Op Fl -strip-unneeded
+.Op Fl w | Fl -wildcard
+.Op Fl x | Fl -discard-all
+.Op Fl I Ar format | Fl -input-target= Ns Ar format
+.Op Fl K Ar symbol | Fl -keep-symbol= Ns Ar symbol
+.Op Fl N Ar symbol | Fl -strip-symbol= Ns Ar symbol
+.Op Fl O Ar format | Fl -output-target= Ns Ar format
+.Op Fl R Ar sectionname | Fl -remove-section= Ns Ar sectionname
+.Op Fl V | Fl -version
+.Op Fl X | Fl -discard-locals
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility is used to discard information from ELF objects.
+.Pp
+The
+.Nm
+utility supports the following options:
+.Bl -tag -width indent
+.It Fl d | Fl g | Fl S | Fl -strip-debug
+Remove debugging symbols only.
+.It Fl h | Fl -help
+Print a help message and exit.
+.It Fl -only-keep-debug
+Remove all content except that which would be used for debugging.
+.It Fl o Ar outputfile | Fl -output-file= Ns Ar outputfile
+Write the stripped object to file
+.Ar outputfile .
+The default behaviour is to modify objects in place.
+.It Fl p | Fl -preserve-dates
+Preserve the object's access and modification times.
+.It Fl s | Fl -strip-all
+Remove all symbols.
+.It Fl -strip-unneeded
+Remove all symbols not needed for further relocation processing.
+.It Fl w | Fl -wildcard
+Use shell-style patterns to name symbols.
+The following meta-characters are recognized in patterns:
+.Bl -tag -width "...." -compact
+.It Li !
+If this is the first character of the pattern, invert the sense of the
+pattern match.
+.It Li *
+Matches any string of characters in a symbol name.
+.It Li ?
+Matches zero or one character in a symbol name.
+.It Li [
+Mark the start of a character class.
+.It Li \e
+Remove the special meaning of the next character in the pattern.
+.It Li ]
+Mark the end of a character class.
+.El
+.It Fl x | Fl -discard-all
+Discard all non-global symbols.
+.It Fl I Ar format | Fl -input-target= Ns Ar format
+These options are accepted, but are ignored.
+.It Fl K Ar symbol | Fl -keep-symbol= Ns Ar symbol
+Keep the symbol
+.Ar symbol
+even if it would otherwise be stripped.
+This option may be specified multiple times.
+.It Fl N Ar symbol | Fl -strip-symbol= Ns Ar symbol
+Remove the symbol
+.Ar symbol
+even if it would otherwise have been kept.
+This option may be specified multiple times.
+.It Fl O Ar format | Fl -output-target= Ns Ar format
+Set the output file format to
+.Ar format .
+For the full list of supported formats, please see the documentation
+for function
+.Xr elftc_bfd_find_target 3 .
+.It Fl R Ar sectionname | Fl -remove-section= Ns Ar sectionname
+Remove the section named by the argument
+.Ar sectionname .
+This option may be specified multiple times.
+.It Fl V | Fl -version
+Print a version identifier and exit.
+.It Fl X | Fl -discard-locals
+Remove compiler-generated local symbols.
+.El
+.Sh DIAGNOSTICS
+.Ex -std
+.Sh SEE ALSO
+.Xr ar 1 ,
+.Xr elfcopy 1 ,
+.Xr ld 1 ,
+.Xr mcs 1 ,
+.Xr elf 3 ,
+.Xr elftc_bfd_find_target 3 ,
+.Xr fnmatch 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/elfcopy/symbols.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,1213 @@
+/*-
+ * Copyright (c) 2007-2013 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <assert.h>
+#include <err.h>
+#include <fnmatch.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "elfcopy.h"
+
+ELFTC_VCSID("$Id: symbols.c 3520 2017-04-17 01:47:52Z kaiwang27 $");
+
+/* Backwards compatibility for systems with older ELF definitions. */
+#ifndef STB_GNU_UNIQUE
+#define	STB_GNU_UNIQUE 10
+#endif
+
+
+/* Symbol table buffer structure. */
+struct symbuf {
+	Elf32_Sym *l32;		/* 32bit local symbol */
+	Elf32_Sym *g32;		/* 32bit global symbol */
+	Elf64_Sym *l64;		/* 64bit local symbol */
+	Elf64_Sym *g64;		/* 64bit global symbol */
+	size_t ngs, nls;	/* number of each kind */
+	size_t gcap, lcap; 	/* buffer capacities. */
+};
+
+struct sthash {
+	LIST_ENTRY(sthash) sh_next;
+	size_t sh_off;
+};
+typedef LIST_HEAD(,sthash) hash_head;
+#define STHASHSIZE 65536
+
+struct strimpl {
+	char *buf;		/* string table */
+	size_t sz;		/* entries */
+	size_t cap;		/* buffer capacity */
+	hash_head hash[STHASHSIZE];
+};
+
+
+/* String table buffer structure. */
+struct strbuf {
+	struct strimpl l;	/* local symbols */
+	struct strimpl g;	/* global symbols */
+};
+
+static int	is_debug_symbol(unsigned char st_info);
+static int	is_global_symbol(unsigned char st_info);
+static int	is_local_symbol(unsigned char st_info);
+static int	is_local_label(const char *name);
+static int	is_needed_symbol(struct elfcopy *ecp, int i, GElf_Sym *s);
+static int	is_remove_symbol(struct elfcopy *ecp, size_t sc, int i,
+		    GElf_Sym *s, const char *name);
+static int	is_weak_symbol(unsigned char st_info);
+static int	lookup_exact_string(hash_head *hash, const char *buf,
+		    const char *s);
+static int	generate_symbols(struct elfcopy *ecp);
+static void	mark_reloc_symbols(struct elfcopy *ecp, size_t sc);
+static void	mark_section_group_symbols(struct elfcopy *ecp, size_t sc);
+uint32_t	str_hash(const char *s);
+
+/* Convenient bit vector operation macros. */
+#define BIT_SET(v, n) (v[(n)>>3] |= 1U << ((n) & 7))
+#define BIT_CLR(v, n) (v[(n)>>3] &= ~(1U << ((n) & 7)))
+#define BIT_ISSET(v, n) (v[(n)>>3] & (1U << ((n) & 7)))
+
+static int
+is_debug_symbol(unsigned char st_info)
+{
+
+	if (GELF_ST_TYPE(st_info) == STT_SECTION ||
+	    GELF_ST_TYPE(st_info) == STT_FILE)
+		return (1);
+
+	return (0);
+}
+
+static int
+is_global_symbol(unsigned char st_info)
+{
+
+	if (GELF_ST_BIND(st_info) == STB_GLOBAL ||
+	    GELF_ST_BIND(st_info) == STB_GNU_UNIQUE)
+		return (1);
+
+	return (0);
+}
+
+static int
+is_weak_symbol(unsigned char st_info)
+{
+
+	if (GELF_ST_BIND(st_info) == STB_WEAK)
+		return (1);
+
+	return (0);
+}
+
+static int
+is_local_symbol(unsigned char st_info)
+{
+
+	if (GELF_ST_BIND(st_info) == STB_LOCAL)
+		return (1);
+
+	return (0);
+}
+
+static int
+is_hidden_symbol(unsigned char st_other)
+{
+
+	if (GELF_ST_VISIBILITY(st_other) == STV_HIDDEN ||
+	    GELF_ST_VISIBILITY(st_other) == STV_INTERNAL)
+		return (1);
+
+	return (0);
+}
+
+static int
+is_local_label(const char *name)
+{
+
+	/* Compiler generated local symbols that start with .L */
+	if (name[0] == '.' && name[1] == 'L')
+		return (1);
+
+	return (0);
+}
+
+/*
+ * Symbols related to relocation are needed.
+ */
+static int
+is_needed_symbol(struct elfcopy *ecp, int i, GElf_Sym *s)
+{
+
+	/* If symbol involves relocation, it is needed. */
+	if (BIT_ISSET(ecp->v_rel, i))
+		return (1);
+
+	/* Symbols referred by COMDAT sections are needed. */
+	if (BIT_ISSET(ecp->v_grp, i))
+		return (1);
+
+	/*
+	 * For relocatable files (.o files), global and weak symbols
+	 * are needed.
+	 */
+	if (ecp->flags & RELOCATABLE) {
+		if (is_global_symbol(s->st_info) || is_weak_symbol(s->st_info))
+			return (1);
+	}
+
+	return (0);
+}
+
+static int
+is_remove_symbol(struct elfcopy *ecp, size_t sc, int i, GElf_Sym *s,
+    const char *name)
+{
+	GElf_Sym sym0 = {
+		0, 		/* st_name */
+		0,		/* st_value */
+		0,		/* st_size */
+		0,		/* st_info */
+		0,		/* st_other */
+		SHN_UNDEF,	/* st_shndx */
+	};
+
+	/*
+	 * Keep the first symbol if it is the special reserved symbol.
+	 * XXX Should we generate one if it's missing?
+	 */
+	if (i == 0 && !memcmp(s, &sym0, sizeof(GElf_Sym)))
+		return (0);
+
+	/* Remove the symbol if the section it refers to was removed. */
+	if (s->st_shndx != SHN_UNDEF && s->st_shndx < SHN_LORESERVE &&
+	    ecp->secndx[s->st_shndx] == 0)
+		return (1);
+
+	/* Keep the symbol if specified by command line option -K. */
+	if (lookup_symop_list(ecp, name, SYMOP_KEEP) != NULL)
+		return (0);
+
+	if (ecp->strip == STRIP_ALL)
+		return (1);
+
+	/* Mark symbols used in relocation. */
+	if (ecp->v_rel == NULL)
+		mark_reloc_symbols(ecp, sc);
+
+	/* Mark symbols used in section groups. */
+	if (ecp->v_grp == NULL)
+		mark_section_group_symbols(ecp, sc);
+
+	/*
+	 * Strip the symbol if specified by command line option -N,
+	 * unless it's used in relocation.
+	 */
+	if (lookup_symop_list(ecp, name, SYMOP_STRIP) != NULL) {
+		if (BIT_ISSET(ecp->v_rel, i)) {
+			warnx("not stripping symbol `%s' because it is named"
+			    " in a relocation", name);
+			return (0);
+		}
+		return (1);
+	}
+
+	if (is_needed_symbol(ecp, i, s))
+		return (0);
+
+	if (ecp->strip == STRIP_UNNEEDED)
+		return (1);
+
+	if ((ecp->flags & DISCARD_LOCAL) && is_local_symbol(s->st_info) &&
+	    !is_debug_symbol(s->st_info))
+		return (1);
+
+	if ((ecp->flags & DISCARD_LLABEL) && is_local_symbol(s->st_info) &&
+	    !is_debug_symbol(s->st_info) && is_local_label(name))
+		return (1);
+
+	if (ecp->strip == STRIP_DEBUG && is_debug_symbol(s->st_info))
+		return (1);
+
+	return (0);
+}
+
+/*
+ * Mark symbols referred by relocation entries.
+ */
+static void
+mark_reloc_symbols(struct elfcopy *ecp, size_t sc)
+{
+	const char	*name;
+	Elf_Data	*d;
+	Elf_Scn		*s;
+	GElf_Rel	 r;
+	GElf_Rela	 ra;
+	GElf_Shdr	 sh;
+	size_t		 n, indx;
+	int		 elferr, i, len;
+
+	ecp->v_rel = calloc((sc + 7) / 8, 1);
+	if (ecp->v_rel == NULL)
+		err(EXIT_FAILURE, "calloc failed");
+
+	if (elf_getshstrndx(ecp->ein, &indx) == 0)
+		errx(EXIT_FAILURE, "elf_getshstrndx failed: %s",
+		    elf_errmsg(-1));
+
+	s = NULL;
+	while ((s = elf_nextscn(ecp->ein, s)) != NULL) {
+		if (gelf_getshdr(s, &sh) != &sh)
+			errx(EXIT_FAILURE, "elf_getshdr failed: %s",
+			    elf_errmsg(-1));
+
+		if (sh.sh_type != SHT_REL && sh.sh_type != SHT_RELA)
+			continue;
+
+		/*
+		 * Skip if this reloc section won't appear in the
+		 * output object.
+		 */
+		if ((name = elf_strptr(ecp->ein, indx, sh.sh_name)) == NULL)
+			errx(EXIT_FAILURE, "elf_strptr failed: %s",
+			    elf_errmsg(-1));
+		if (is_remove_section(ecp, name) ||
+		    is_remove_reloc_sec(ecp, sh.sh_info))
+			continue;
+
+		/* Skip if it's not for .symtab */
+		if (sh.sh_link != elf_ndxscn(ecp->symtab->is))
+			continue;
+
+		d = NULL;
+		n = 0;
+		while (n < sh.sh_size && (d = elf_getdata(s, d)) != NULL) {
+			len = d->d_size / sh.sh_entsize;
+			for (i = 0; i < len; i++) {
+				if (sh.sh_type == SHT_REL) {
+					if (gelf_getrel(d, i, &r) != &r)
+						errx(EXIT_FAILURE,
+						    "elf_getrel failed: %s",
+						     elf_errmsg(-1));
+					n = GELF_R_SYM(r.r_info);
+				} else {
+					if (gelf_getrela(d, i, &ra) != &ra)
+						errx(EXIT_FAILURE,
+						    "elf_getrela failed: %s",
+						     elf_errmsg(-1));
+					n = GELF_R_SYM(ra.r_info);
+				}
+				if (n > 0 && n < sc)
+					BIT_SET(ecp->v_rel, n);
+				else if (n != 0)
+					warnx("invalid symbox index");
+			}
+		}
+		elferr = elf_errno();
+		if (elferr != 0)
+			errx(EXIT_FAILURE, "elf_getdata failed: %s",
+			    elf_errmsg(elferr));
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		errx(EXIT_FAILURE, "elf_nextscn failed: %s",
+		    elf_errmsg(elferr));
+}
+
+static void
+mark_section_group_symbols(struct elfcopy *ecp, size_t sc)
+{
+	const char	*name;
+	Elf_Scn		*s;
+	GElf_Shdr	 sh;
+	size_t		 indx;
+	int		 elferr;
+
+	ecp->v_grp = calloc((sc + 7) / 8, 1);
+	if (ecp->v_grp == NULL)
+		err(EXIT_FAILURE, "calloc failed");
+
+	if (elf_getshstrndx(ecp->ein, &indx) == 0)
+		errx(EXIT_FAILURE, "elf_getshstrndx failed: %s",
+		    elf_errmsg(-1));
+
+	s = NULL;
+	while ((s = elf_nextscn(ecp->ein, s)) != NULL) {
+		if (gelf_getshdr(s, &sh) != &sh)
+			errx(EXIT_FAILURE, "elf_getshdr failed: %s",
+			    elf_errmsg(-1));
+
+		if (sh.sh_type != SHT_GROUP)
+			continue;
+
+		if ((name = elf_strptr(ecp->ein, indx, sh.sh_name)) == NULL)
+			errx(EXIT_FAILURE, "elf_strptr failed: %s",
+			    elf_errmsg(-1));
+		if (is_remove_section(ecp, name))
+			continue;
+
+		if (sh.sh_info > 0 && sh.sh_info < sc)
+			BIT_SET(ecp->v_grp, sh.sh_info);
+		else if (sh.sh_info != 0)
+			warnx("invalid symbox index");
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		errx(EXIT_FAILURE, "elf_nextscn failed: %s",
+		    elf_errmsg(elferr));
+}
+
+static int
+generate_symbols(struct elfcopy *ecp)
+{
+	struct section	*s;
+	struct symop	*sp;
+	struct symbuf	*sy_buf;
+	struct strbuf	*st_buf;
+	const char	*name;
+	char		*newname;
+	unsigned char	*gsym;
+	GElf_Shdr	 ish;
+	GElf_Sym	 sym;
+	Elf_Data*	 id;
+	Elf_Scn		*is;
+	size_t		 ishstrndx, namelen, ndx, sc, symndx;
+	int		 ec, elferr, i;
+
+	if (elf_getshstrndx(ecp->ein, &ishstrndx) == 0)
+		errx(EXIT_FAILURE, "elf_getshstrndx failed: %s",
+		    elf_errmsg(-1));
+	if ((ec = gelf_getclass(ecp->eout)) == ELFCLASSNONE)
+		errx(EXIT_FAILURE, "gelf_getclass failed: %s",
+		    elf_errmsg(-1));
+
+	/* Create buffers for .symtab and .strtab. */
+	if ((sy_buf = calloc(1, sizeof(*sy_buf))) == NULL)
+		err(EXIT_FAILURE, "calloc failed");
+	if ((st_buf = calloc(1, sizeof(*st_buf))) == NULL)
+		err(EXIT_FAILURE, "calloc failed");
+	sy_buf->gcap = sy_buf->lcap = 64;
+	st_buf->g.cap = 256;
+	st_buf->l.cap = 64;
+	st_buf->l.sz = 1;	/* '\0' at start. */
+	st_buf->g.sz = 0;
+
+	ecp->symtab->sz = 0;
+	ecp->strtab->sz = 0;
+	ecp->symtab->buf = sy_buf;
+	ecp->strtab->buf = st_buf;
+
+	gsym = NULL;
+
+	/*
+	 * Create bit vector v_secsym, which is used to mark sections
+	 * that already have corresponding STT_SECTION symbols.
+	 */
+	ecp->v_secsym = calloc((ecp->nos + 7) / 8, 1);
+	if (ecp->v_secsym == NULL)
+		err(EXIT_FAILURE, "calloc failed");
+
+	/* Locate .strtab of input object. */
+	symndx = 0;
+	name = NULL;
+	is = NULL;
+	while ((is = elf_nextscn(ecp->ein, is)) != NULL) {
+		if (gelf_getshdr(is, &ish) != &ish)
+			errx(EXIT_FAILURE, "elf_getshdr failed: %s",
+			    elf_errmsg(-1));
+		if ((name = elf_strptr(ecp->ein, ishstrndx, ish.sh_name)) ==
+		    NULL)
+			errx(EXIT_FAILURE, "elf_strptr failed: %s",
+			    elf_errmsg(-1));
+		if (strcmp(name, ".strtab") == 0) {
+			symndx = elf_ndxscn(is);
+			break;
+		}
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		errx(EXIT_FAILURE, "elf_nextscn failed: %s",
+		    elf_errmsg(elferr));
+
+	/* Symbol table should exist if this function is called. */
+	if (symndx == 0) {
+		warnx("can't find .strtab section");
+		goto clean;
+	}
+
+	/* Locate .symtab of input object. */
+	is = NULL;
+	while ((is = elf_nextscn(ecp->ein, is)) != NULL) {
+		if (gelf_getshdr(is, &ish) != &ish)
+			errx(EXIT_FAILURE, "elf_getshdr failed: %s",
+			    elf_errmsg(-1));
+		if ((name = elf_strptr(ecp->ein, ishstrndx, ish.sh_name)) ==
+		    NULL)
+			errx(EXIT_FAILURE, "elf_strptr failed: %s",
+			    elf_errmsg(-1));
+		if (strcmp(name, ".symtab") == 0)
+			break;
+	}
+	elferr = elf_errno();
+	if (elferr != 0)
+		errx(EXIT_FAILURE, "elf_nextscn failed: %s",
+		    elf_errmsg(elferr));
+	if (is == NULL)
+		errx(EXIT_FAILURE, "can't find .strtab section");
+
+	/*
+	 * Create bit vector gsym to mark global symbols, and symndx
+	 * to keep track of symbol index changes from input object to
+	 * output object, it is used by update_reloc() later to update
+	 * relocation information.
+	 */
+	sc = ish.sh_size / ish.sh_entsize;
+	if (sc > 0) {
+		ecp->symndx = calloc(sc, sizeof(*ecp->symndx));
+		if (ecp->symndx == NULL)
+			err(EXIT_FAILURE, "calloc failed");
+		gsym = calloc((sc + 7) / 8, sizeof(*gsym));
+		if (gsym == NULL)
+			err(EXIT_FAILURE, "calloc failed");
+		if ((id = elf_getdata(is, NULL)) == NULL) {
+			elferr = elf_errno();
+			if (elferr != 0)
+				errx(EXIT_FAILURE, "elf_getdata failed: %s",
+				    elf_errmsg(elferr));
+			goto clean;
+		}
+	} else
+		return (0);
+
+	/* Copy/Filter each symbol. */
+	for (i = 0; (size_t)i < sc; i++) {
+		if (gelf_getsym(id, i, &sym) != &sym)
+			errx(EXIT_FAILURE, "gelf_getsym failed: %s",
+			    elf_errmsg(-1));
+		if ((name = elf_strptr(ecp->ein, symndx, sym.st_name)) == NULL)
+			errx(EXIT_FAILURE, "elf_strptr failed: %s",
+			    elf_errmsg(-1));
+
+		/* Symbol filtering. */
+		if (is_remove_symbol(ecp, sc, i, &sym, name) != 0)
+			continue;
+
+		/* Check if we need to change the binding of this symbol. */
+		if (is_global_symbol(sym.st_info) ||
+		    is_weak_symbol(sym.st_info)) {
+			/*
+			 * XXX Binutils objcopy does not weaken certain
+			 * symbols.
+			 */
+			if (ecp->flags & WEAKEN_ALL ||
+			    lookup_symop_list(ecp, name, SYMOP_WEAKEN) != NULL)
+				sym.st_info = GELF_ST_INFO(STB_WEAK,
+				    GELF_ST_TYPE(sym.st_info));
+			/* Do not localize undefined symbols. */
+			if (sym.st_shndx != SHN_UNDEF &&
+			    lookup_symop_list(ecp, name, SYMOP_LOCALIZE) !=
+			    NULL)
+				sym.st_info = GELF_ST_INFO(STB_LOCAL,
+				    GELF_ST_TYPE(sym.st_info));
+			if (ecp->flags & KEEP_GLOBAL &&
+			    sym.st_shndx != SHN_UNDEF &&
+			    lookup_symop_list(ecp, name, SYMOP_KEEPG) == NULL)
+				sym.st_info = GELF_ST_INFO(STB_LOCAL,
+				    GELF_ST_TYPE(sym.st_info));
+			if (ecp->flags & LOCALIZE_HIDDEN &&
+			    sym.st_shndx != SHN_UNDEF &&
+			    is_hidden_symbol(sym.st_other))
+				sym.st_info = GELF_ST_INFO(STB_LOCAL,
+				    GELF_ST_TYPE(sym.st_info));
+		} else {
+			/* STB_LOCAL binding. */
+			if (lookup_symop_list(ecp, name, SYMOP_GLOBALIZE) !=
+			    NULL)
+				sym.st_info = GELF_ST_INFO(STB_GLOBAL,
+				    GELF_ST_TYPE(sym.st_info));
+			/* XXX We should globalize weak symbol? */
+		}
+
+		/* Check if we need to rename this symbol. */
+		if ((sp = lookup_symop_list(ecp, name, SYMOP_REDEF)) != NULL)
+			name = sp->newname;
+
+		/* Check if we need to prefix the symbols. */
+		newname = NULL;
+		if (ecp->prefix_sym != NULL && name != NULL && *name != '\0') {
+			namelen = strlen(name) + strlen(ecp->prefix_sym) + 1;
+			if ((newname = malloc(namelen)) == NULL)
+				err(EXIT_FAILURE, "malloc failed");
+			snprintf(newname, namelen, "%s%s", ecp->prefix_sym,
+			    name);
+			name = newname;
+		}
+
+		/* Copy symbol, mark global/weak symbol and add to index map. */
+		if (is_global_symbol(sym.st_info) ||
+		    is_weak_symbol(sym.st_info)) {
+			BIT_SET(gsym, i);
+			ecp->symndx[i] = sy_buf->ngs;
+		} else
+			ecp->symndx[i] = sy_buf->nls;
+		add_to_symtab(ecp, name, sym.st_value, sym.st_size,
+		    sym.st_shndx, sym.st_info, sym.st_other, 0);
+
+		if (newname != NULL)
+			free(newname);
+
+		/*
+		 * If the symbol is a STT_SECTION symbol, mark the section
+		 * it points to.
+		 */
+		if (GELF_ST_TYPE(sym.st_info) == STT_SECTION &&
+		    sym.st_shndx < SHN_LORESERVE) {
+			assert(ecp->secndx[sym.st_shndx] < (uint64_t)ecp->nos);
+			BIT_SET(ecp->v_secsym, ecp->secndx[sym.st_shndx]);
+		}
+	}
+
+	/*
+	 * Give up if there is no real symbols inside the table.
+	 * XXX The logic here needs to be improved. We need to
+	 * check if that only local symbol is the reserved symbol.
+	 */
+	if (sy_buf->nls <= 1 && sy_buf->ngs == 0)
+		goto clean;
+
+	/*
+	 * Create STT_SECTION symbols for sections that do not already
+	 * got one. However, we do not create STT_SECTION symbol for
+	 * .symtab, .strtab, .shstrtab and reloc sec of relocatables.
+	 */
+	TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
+		if (s->pseudo)
+			continue;
+		if (strcmp(s->name, ".symtab") == 0 ||
+		    strcmp(s->name, ".strtab") == 0 ||
+		    strcmp(s->name, ".shstrtab") == 0)
+			continue;
+		if ((ecp->flags & RELOCATABLE) != 0 &&
+		    ((s->type == SHT_REL) || (s->type == SHT_RELA)))
+			continue;
+
+		if ((ndx = elf_ndxscn(s->os)) == SHN_UNDEF)
+			errx(EXIT_FAILURE, "elf_ndxscn failed: %s",
+			    elf_errmsg(-1));
+
+		if (!BIT_ISSET(ecp->v_secsym, ndx)) {
+			sym.st_name  = 0;
+			sym.st_value = s->vma;
+			sym.st_size  = 0;
+			sym.st_info  = GELF_ST_INFO(STB_LOCAL, STT_SECTION);
+			sym.st_other = STV_DEFAULT;
+			/*
+			 * Don't let add_to_symtab() touch sym.st_shndx.
+			 * In this case, we know the index already.
+			 */
+			add_to_symtab(ecp, NULL, sym.st_value, sym.st_size,
+			    ndx, sym.st_info, sym.st_other, 1);
+		}
+	}
+
+	/*
+	 * Update st_name and index map for global/weak symbols. Note that
+	 * global/weak symbols are put after local symbols.
+	 */
+	if (gsym != NULL) {
+		for(i = 0; (size_t) i < sc; i++) {
+			if (!BIT_ISSET(gsym, i))
+				continue;
+
+			/* Update st_name. */
+			if (ec == ELFCLASS32)
+				sy_buf->g32[ecp->symndx[i]].st_name +=
+				    st_buf->l.sz;
+			else
+				sy_buf->g64[ecp->symndx[i]].st_name +=
+				    st_buf->l.sz;
+
+			/* Update index map. */
+			ecp->symndx[i] += sy_buf->nls;
+		}
+		free(gsym);
+	}
+
+	return (1);
+
+clean:
+	free(gsym);
+	free_symtab(ecp);
+
+	return (0);
+}
+
+void
+create_symtab(struct elfcopy *ecp)
+{
+	struct section	*s, *sy, *st;
+	size_t		 maxndx, ndx;
+
+	sy = ecp->symtab;
+	st = ecp->strtab;
+
+	assert(sy != NULL && st != NULL);
+
+	/*
+	 * Set section index map for .symtab and .strtab. We need to set
+	 * these map because otherwise symbols which refer to .symtab and
+	 * .strtab will be removed by symbol filtering unconditionally.
+	 * And we have to figure out scn index this way (instead of calling
+	 * elf_ndxscn) because we can not create Elf_Scn before we're certain
+	 * that .symtab and .strtab will exist in the output object.
+	 */
+	maxndx = 0;
+	TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
+		if (s->os == NULL)
+			continue;
+		if ((ndx = elf_ndxscn(s->os)) == SHN_UNDEF)
+			errx(EXIT_FAILURE, "elf_ndxscn failed: %s",
+			    elf_errmsg(-1));
+		if (ndx > maxndx)
+			maxndx = ndx;
+	}
+	ecp->secndx[elf_ndxscn(sy->is)] = maxndx + 1;
+	ecp->secndx[elf_ndxscn(st->is)] = maxndx + 2;
+
+	/*
+	 * Generate symbols for output object if SYMTAB_INTACT is not set.
+	 * If there is no symbol in the input object or all the symbols are
+	 * stripped, then free all the resouces allotted for symbol table,
+	 * and clear SYMTAB_EXIST flag.
+	 */
+	if (((ecp->flags & SYMTAB_INTACT) == 0) && !generate_symbols(ecp)) {
+		TAILQ_REMOVE(&ecp->v_sec, ecp->symtab, sec_list);
+		TAILQ_REMOVE(&ecp->v_sec, ecp->strtab, sec_list);
+		free(ecp->symtab->buf);
+		free(ecp->symtab);
+		free(ecp->strtab->buf);
+		free(ecp->strtab);
+		ecp->symtab = NULL;
+		ecp->strtab = NULL;
+		ecp->flags &= ~SYMTAB_EXIST;
+		return;
+	}
+
+	/* Create output Elf_Scn for .symtab and .strtab. */
+	if ((sy->os = elf_newscn(ecp->eout)) == NULL ||
+	    (st->os = elf_newscn(ecp->eout)) == NULL)
+		errx(EXIT_FAILURE, "elf_newscn failed: %s",
+		    elf_errmsg(-1));
+	/* Update secndx anyway. */
+	ecp->secndx[elf_ndxscn(sy->is)] = elf_ndxscn(sy->os);
+	ecp->secndx[elf_ndxscn(st->is)] = elf_ndxscn(st->os);
+
+	/*
+	 * Copy .symtab and .strtab section headers from input to output
+	 * object to start with, these will be overridden later if need.
+	 */
+	copy_shdr(ecp, sy, ".symtab", 1, 0);
+	copy_shdr(ecp, st, ".strtab", 1, 0);
+
+	/* Copy verbatim if symbol table is intact. */
+	if (ecp->flags & SYMTAB_INTACT) {
+		copy_data(sy);
+		copy_data(st);
+		return;
+	}
+
+	create_symtab_data(ecp);
+}
+
+void
+free_symtab(struct elfcopy *ecp)
+{
+	struct symbuf	*sy_buf;
+	struct strbuf	*st_buf;
+	struct sthash	*sh, *shtmp;
+	int i;
+
+	if (ecp->symtab != NULL && ecp->symtab->buf != NULL) {
+		sy_buf = ecp->symtab->buf;
+		if (sy_buf->l32 != NULL)
+			free(sy_buf->l32);
+		if (sy_buf->g32 != NULL)
+			free(sy_buf->g32);
+		if (sy_buf->l64 != NULL)
+			free(sy_buf->l64);
+		if (sy_buf->g64 != NULL)
+			free(sy_buf->g64);
+	}
+
+	if (ecp->strtab != NULL && ecp->strtab->buf != NULL) {
+		st_buf = ecp->strtab->buf;
+		if (st_buf->l.buf != NULL)
+			free(st_buf->l.buf);
+		if (st_buf->g.buf != NULL)
+			free(st_buf->g.buf);
+		for (i = 0; i < STHASHSIZE; i++) {
+			LIST_FOREACH_SAFE(sh, &st_buf->l.hash[i], sh_next,
+			    shtmp) {
+				LIST_REMOVE(sh, sh_next);
+				free(sh);
+			}
+			LIST_FOREACH_SAFE(sh, &st_buf->g.hash[i], sh_next,
+			    shtmp) {
+				LIST_REMOVE(sh, sh_next);
+				free(sh);
+			}
+		}
+	}
+
+	if (ecp->symndx != NULL) {
+		free(ecp->symndx);
+		ecp->symndx = NULL;
+	}
+	if (ecp->v_rel != NULL) {
+		free(ecp->v_rel);
+		ecp->v_rel = NULL;
+	}
+	if (ecp->v_grp != NULL) {
+		free(ecp->v_grp);
+		ecp->v_grp = NULL;
+	}
+	if (ecp->v_secsym != NULL) {
+		free(ecp->v_secsym);
+		ecp->v_secsym = NULL;
+	}
+}
+
+void
+create_external_symtab(struct elfcopy *ecp)
+{
+	struct section *s;
+	struct symbuf *sy_buf;
+	struct strbuf *st_buf;
+	GElf_Shdr sh;
+	size_t ndx;
+
+	if (ecp->oec == ELFCLASS32)
+		ecp->symtab = create_external_section(ecp, ".symtab", NULL,
+		    NULL, 0, 0, SHT_SYMTAB, ELF_T_SYM, 0, 4, 0, 0);
+	else
+		ecp->symtab = create_external_section(ecp, ".symtab", NULL,
+		    NULL, 0, 0, SHT_SYMTAB, ELF_T_SYM, 0, 8, 0, 0);
+
+	ecp->strtab = create_external_section(ecp, ".strtab", NULL, NULL, 0, 0,
+	    SHT_STRTAB, ELF_T_BYTE, 0, 1, 0, 0);
+
+	/* Let sh_link field of .symtab section point to .strtab section. */
+	if (gelf_getshdr(ecp->symtab->os, &sh) == NULL)
+		errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
+		    elf_errmsg(-1));
+	sh.sh_link = elf_ndxscn(ecp->strtab->os);
+	if (!gelf_update_shdr(ecp->symtab->os, &sh))
+		errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s",
+		    elf_errmsg(-1));
+
+	/* Create buffers for .symtab and .strtab. */
+	if ((sy_buf = calloc(1, sizeof(*sy_buf))) == NULL)
+		err(EXIT_FAILURE, "calloc failed");
+	if ((st_buf = calloc(1, sizeof(*st_buf))) == NULL)
+		err(EXIT_FAILURE, "calloc failed");
+	sy_buf->gcap = sy_buf->lcap = 64;
+	st_buf->g.cap = 256;
+	st_buf->l.cap = 64;
+	st_buf->l.sz = 1;	/* '\0' at start. */
+	st_buf->g.sz = 0;
+
+	ecp->symtab->sz = 0;
+	ecp->strtab->sz = 0;
+	ecp->symtab->buf = sy_buf;
+	ecp->strtab->buf = st_buf;
+
+	/* Always create the special symbol at the symtab beginning. */
+	add_to_symtab(ecp, NULL, 0, 0, SHN_UNDEF,
+	    ELF32_ST_INFO(STB_LOCAL, STT_NOTYPE), 0, 1);
+
+	/* Create STT_SECTION symbols. */
+	TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
+		if (s->pseudo)
+			continue;
+		if (strcmp(s->name, ".symtab") == 0 ||
+		    strcmp(s->name, ".strtab") == 0 ||
+		    strcmp(s->name, ".shstrtab") == 0)
+			continue;
+		(void) elf_errno();
+		if ((ndx = elf_ndxscn(s->os)) == SHN_UNDEF) {
+			warnx("elf_ndxscn failed: %s",
+			    elf_errmsg(-1));
+			continue;
+		}
+		add_to_symtab(ecp, NULL, 0, 0, ndx,
+		    GELF_ST_INFO(STB_LOCAL, STT_SECTION), 0, 1);
+	}
+}
+
+void
+add_to_symtab(struct elfcopy *ecp, const char *name, uint64_t st_value,
+    uint64_t st_size, uint16_t st_shndx, unsigned char st_info,
+    unsigned char st_other, int ndx_known)
+{
+	struct symbuf *sy_buf;
+	struct strbuf *st_buf;
+	struct sthash *sh;
+	uint32_t hash;
+	int pos;
+
+	/*
+	 * Convenient macro for copying global/local 32/64 bit symbols
+	 * from input object to the buffer created for output object.
+	 * It handles buffer growing, st_name calculating and st_shndx
+	 * updating for symbols with non-special section index.
+	 */
+#define	_ST_NAME_EMPTY_l 0
+#define	_ST_NAME_EMPTY_g -1
+#define	_ADDSYM(B, SZ) do {						\
+	if (sy_buf->B##SZ == NULL) {					\
+		sy_buf->B##SZ = malloc(sy_buf->B##cap *			\
+		    sizeof(Elf##SZ##_Sym));				\
+		if (sy_buf->B##SZ == NULL)				\
+			err(EXIT_FAILURE, "malloc failed");		\
+	} else if (sy_buf->n##B##s >= sy_buf->B##cap) {			\
+		sy_buf->B##cap *= 2;					\
+		sy_buf->B##SZ = realloc(sy_buf->B##SZ, sy_buf->B##cap *	\
+		    sizeof(Elf##SZ##_Sym));				\
+		if (sy_buf->B##SZ == NULL)				\
+			err(EXIT_FAILURE, "realloc failed");		\
+	}								\
+	sy_buf->B##SZ[sy_buf->n##B##s].st_info	= st_info;		\
+	sy_buf->B##SZ[sy_buf->n##B##s].st_other	= st_other;		\
+	sy_buf->B##SZ[sy_buf->n##B##s].st_value	= st_value;		\
+	sy_buf->B##SZ[sy_buf->n##B##s].st_size	= st_size;		\
+	if (ndx_known)							\
+		sy_buf->B##SZ[sy_buf->n##B##s].st_shndx = st_shndx;	\
+	else if (st_shndx == SHN_UNDEF || st_shndx >= SHN_LORESERVE)	\
+		sy_buf->B##SZ[sy_buf->n##B##s].st_shndx = st_shndx;	\
+	else								\
+		sy_buf->B##SZ[sy_buf->n##B##s].st_shndx	=		\
+			ecp->secndx[st_shndx];				\
+	if (st_buf->B.buf == NULL) {					\
+		st_buf->B.buf = calloc(st_buf->B.cap,			\
+		    sizeof(*st_buf->B.buf));				\
+		if (st_buf->B.buf == NULL)				\
+			err(EXIT_FAILURE, "malloc failed");		\
+	}								\
+	if (name != NULL && *name != '\0') {				\
+		pos = lookup_exact_string(st_buf->B.hash, st_buf->B.buf,\
+		    name);						\
+		if (pos != -1)						\
+			sy_buf->B##SZ[sy_buf->n##B##s].st_name = pos;	\
+		else {							\
+			sy_buf->B##SZ[sy_buf->n##B##s].st_name =	\
+			    st_buf->B.sz;				\
+			while (st_buf->B.sz + strlen(name) >=		\
+			    st_buf->B.cap - 1) {			\
+				st_buf->B.cap *= 2;			\
+				st_buf->B.buf = realloc(st_buf->B.buf,	\
+				    st_buf->B.cap);			\
+				if (st_buf->B.buf == NULL)		\
+					err(EXIT_FAILURE,		\
+					    "realloc failed");		\
+			}						\
+			if ((sh = malloc(sizeof(*sh))) == NULL)		\
+				err(EXIT_FAILURE, "malloc failed");	\
+			sh->sh_off = st_buf->B.sz;			\
+			hash = str_hash(name);				\
+			LIST_INSERT_HEAD(&st_buf->B.hash[hash], sh,	\
+			    sh_next);					\
+			strncpy(&st_buf->B.buf[st_buf->B.sz], name,	\
+			    strlen(name));				\
+			st_buf->B.buf[st_buf->B.sz + strlen(name)] = '\0'; \
+			st_buf->B.sz += strlen(name) + 1;		\
+		}							\
+	} else								\
+		sy_buf->B##SZ[sy_buf->n##B##s].st_name = 		\
+		    (Elf##SZ##_Word)_ST_NAME_EMPTY_##B;			\
+	sy_buf->n##B##s++;						\
+} while (0)
+
+	sy_buf = ecp->symtab->buf;
+	st_buf = ecp->strtab->buf;
+
+	if (ecp->oec == ELFCLASS32) {
+		if (is_local_symbol(st_info))
+			_ADDSYM(l, 32);
+		else
+			_ADDSYM(g, 32);
+	} else {
+		if (is_local_symbol(st_info))
+			_ADDSYM(l, 64);
+		else
+			_ADDSYM(g, 64);
+	}
+
+	/* Update section size. */
+	ecp->symtab->sz = (sy_buf->nls + sy_buf->ngs) *
+	    (ecp->oec == ELFCLASS32 ? sizeof(Elf32_Sym) : sizeof(Elf64_Sym));
+	ecp->strtab->sz = st_buf->l.sz + st_buf->g.sz;
+
+#undef	_ADDSYM
+#undef	_ST_NAME_EMPTY_l
+#undef	_ST_NAME_EMPTY_g
+}
+
+void
+finalize_external_symtab(struct elfcopy *ecp)
+{
+	struct symbuf *sy_buf;
+	struct strbuf *st_buf;
+	int i;
+
+	/*
+	 * Update st_name for global/weak symbols. (global/weak symbols
+	 * are put after local symbols)
+	 */
+	sy_buf = ecp->symtab->buf;
+	st_buf = ecp->strtab->buf;
+	for (i = 0; (size_t) i < sy_buf->ngs; i++) {
+		if (ecp->oec == ELFCLASS32) {
+			if (sy_buf->g32[i].st_name == (Elf32_Word)-1)
+				sy_buf->g32[i].st_name = 0;
+			else
+				sy_buf->g32[i].st_name += st_buf->l.sz;
+		} else {
+			if (sy_buf->g64[i].st_name == (Elf64_Word)-1)
+				sy_buf->g64[i].st_name = 0;
+			else
+				sy_buf->g64[i].st_name += st_buf->l.sz;
+		}
+	}
+}
+
+void
+create_symtab_data(struct elfcopy *ecp)
+{
+	struct section	*sy, *st;
+	struct symbuf	*sy_buf;
+	struct strbuf	*st_buf;
+	Elf_Data	*gsydata, *lsydata, *gstdata, *lstdata;
+	GElf_Shdr	 shy, sht;
+
+	sy = ecp->symtab;
+	st = ecp->strtab;
+
+	if (gelf_getshdr(sy->os, &shy) == NULL)
+		errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
+		    elf_errmsg(-1));
+	if (gelf_getshdr(st->os, &sht) == NULL)
+		errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
+		    elf_errmsg(-1));
+
+	/*
+	 * Create two Elf_Data for .symtab section of output object, one
+	 * for local symbols and another for global symbols. Note that
+	 * local symbols appear first in the .symtab.
+	 */
+	sy_buf = sy->buf;
+	if (sy_buf->nls > 0) {
+		if ((lsydata = elf_newdata(sy->os)) == NULL)
+			errx(EXIT_FAILURE, "elf_newdata() failed: %s.",
+			     elf_errmsg(-1));
+		if (ecp->oec == ELFCLASS32) {
+			lsydata->d_align	= 4;
+			lsydata->d_off		= 0;
+			lsydata->d_buf		= sy_buf->l32;
+			lsydata->d_size		= sy_buf->nls *
+				sizeof(Elf32_Sym);
+			lsydata->d_type		= ELF_T_SYM;
+			lsydata->d_version	= EV_CURRENT;
+		} else {
+			lsydata->d_align	= 8;
+			lsydata->d_off		= 0;
+			lsydata->d_buf		= sy_buf->l64;
+			lsydata->d_size		= sy_buf->nls *
+				sizeof(Elf64_Sym);
+			lsydata->d_type		= ELF_T_SYM;
+			lsydata->d_version	= EV_CURRENT;
+		}
+	}
+	if (sy_buf->ngs > 0) {
+		if ((gsydata = elf_newdata(sy->os)) == NULL)
+			errx(EXIT_FAILURE, "elf_newdata() failed: %s.",
+			     elf_errmsg(-1));
+		if (ecp->oec == ELFCLASS32) {
+			gsydata->d_align	= 4;
+			gsydata->d_off		= sy_buf->nls *
+				sizeof(Elf32_Sym);
+			gsydata->d_buf		= sy_buf->g32;
+			gsydata->d_size		= sy_buf->ngs *
+				sizeof(Elf32_Sym);
+			gsydata->d_type		= ELF_T_SYM;
+			gsydata->d_version	= EV_CURRENT;
+		} else {
+			gsydata->d_align	= 8;
+			gsydata->d_off		= sy_buf->nls *
+				sizeof(Elf64_Sym);
+			gsydata->d_buf		= sy_buf->g64;
+			gsydata->d_size		= sy_buf->ngs *
+				sizeof(Elf64_Sym);
+			gsydata->d_type		= ELF_T_SYM;
+			gsydata->d_version	= EV_CURRENT;
+		}
+	}
+
+	/*
+	 * Create two Elf_Data for .strtab, one for local symbol name
+	 * and another for globals. Same as .symtab, local symbol names
+	 * appear first.
+	 */
+	st_buf = st->buf;
+	if ((lstdata = elf_newdata(st->os)) == NULL)
+		errx(EXIT_FAILURE, "elf_newdata() failed: %s.",
+		    elf_errmsg(-1));
+	lstdata->d_align	= 1;
+	lstdata->d_off		= 0;
+	lstdata->d_buf		= st_buf->l.buf;
+	lstdata->d_size		= st_buf->l.sz;
+	lstdata->d_type		= ELF_T_BYTE;
+	lstdata->d_version	= EV_CURRENT;
+
+	if (st_buf->g.sz > 0) {
+		if ((gstdata = elf_newdata(st->os)) == NULL)
+			errx(EXIT_FAILURE, "elf_newdata() failed: %s.",
+			    elf_errmsg(-1));
+		gstdata->d_align	= 1;
+		gstdata->d_off		= lstdata->d_size;
+		gstdata->d_buf		= st_buf->g.buf;
+		gstdata->d_size		= st_buf->g.sz;
+		gstdata->d_type		= ELF_T_BYTE;
+		gstdata->d_version	= EV_CURRENT;
+	}
+
+	shy.sh_addr		= 0;
+	shy.sh_addralign	= (ecp->oec == ELFCLASS32 ? 4 : 8);
+	shy.sh_size		= sy->sz;
+	shy.sh_type		= SHT_SYMTAB;
+	shy.sh_flags		= 0;
+	shy.sh_entsize		= gelf_fsize(ecp->eout, ELF_T_SYM, 1,
+	    EV_CURRENT);
+	/*
+	 * According to SYSV abi, here sh_info is one greater than
+	 * the symbol table index of the last local symbol(binding
+	 * STB_LOCAL).
+	 */
+	shy.sh_info		= sy_buf->nls;
+
+	sht.sh_addr		= 0;
+	sht.sh_addralign	= 1;
+	sht.sh_size		= st->sz;
+	sht.sh_type		= SHT_STRTAB;
+	sht.sh_flags		= 0;
+	sht.sh_entsize		= 0;
+	sht.sh_info		= 0;
+	sht.sh_link		= 0;
+
+	if (!gelf_update_shdr(sy->os, &shy))
+		errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s",
+		    elf_errmsg(-1));
+	if (!gelf_update_shdr(st->os, &sht))
+		errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s",
+		    elf_errmsg(-1));
+}
+
+void
+add_to_symop_list(struct elfcopy *ecp, const char *name, const char *newname,
+    unsigned int op)
+{
+	struct symop *s;
+
+	assert (name != NULL);
+	STAILQ_FOREACH(s, &ecp->v_symop, symop_list)
+		if (!strcmp(name, s->name))
+			goto found;
+
+	if ((s = calloc(1, sizeof(*s))) == NULL)
+		errx(EXIT_FAILURE, "not enough memory");
+	STAILQ_INSERT_TAIL(&ecp->v_symop, s, symop_list);
+	s->name = name;
+found:
+	if (op == SYMOP_REDEF)
+		s->newname = newname;
+	s->op |= op;
+}
+
+struct symop *
+lookup_symop_list(struct elfcopy *ecp, const char *name, unsigned int op)
+{
+	struct symop *s, *ret;
+	const char *pattern;
+
+	STAILQ_FOREACH(s, &ecp->v_symop, symop_list) {
+		if ((s->op & op) == 0)
+			continue;
+		if (name == NULL || !strcmp(name, s->name))
+			return (s);
+		if ((ecp->flags & WILDCARD) == 0)
+			continue;
+
+		/* Handle wildcards. */
+		pattern = s->name;
+		if (pattern[0] == '!') {
+			/* Negative match. */
+			pattern++;
+			ret = NULL;
+		} else {
+			/* Regular wildcard match. */
+			ret = s;
+		}
+		if (!fnmatch(pattern, name, 0))
+			return (ret);
+	}
+
+	return (NULL);
+}
+
+static int
+lookup_exact_string(hash_head *buckets, const char *buf, const char *s)
+{
+	struct sthash	*sh;
+	uint32_t	 hash;
+
+	hash = str_hash(s);
+	LIST_FOREACH(sh, &buckets[hash], sh_next)
+		if (strcmp(buf + sh->sh_off, s) == 0)
+			return sh->sh_off;
+	return (-1);
+}
+
+uint32_t
+str_hash(const char *s)
+{
+	uint32_t hash;
+
+	for (hash = 2166136261UL; *s; s++)
+		hash = (hash ^ *s) * 16777619;
+
+	return (hash & (STHASHSIZE - 1));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/elfdump/Makefile	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,11 @@
+# $Id: Makefile 2289 2011-12-04 07:11:47Z jkoshy $
+
+TOP=	..
+
+PROG=	elfdump
+WARNS?=	6
+
+DPADD=	${LIBELFTC} ${LIBELF}
+LDADD=	-lelftc -lelf
+
+.include "${TOP}/mk/elftoolchain.prog.mk"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/elfdump/elfdump.1	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,158 @@
+.\" Copyright (c) 2003 David O'Brien
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: src/usr.bin/elfdump/elfdump.1,v 1.6 2005/01/18 13:43:48 ru Exp $
+.\" $Id: elfdump.1 3231 2015-07-30 13:47:56Z emaste $
+.\"
+.Dd August 25, 2011
+.Dt ELFDUMP 1
+.Os
+.Sh NAME
+.Nm elfdump
+.Nd "display information about"
+.Tn ELF
+files
+.Sh SYNOPSIS
+.Nm
+.Fl a | cdeGhiknprsv
+.Op Fl S
+.Op Fl V
+.Op Fl N Ar name
+.Op Fl w Ar file
+.Ar file ...
+.Sh DESCRIPTION
+The
+.Nm
+utility
+dumps various information about the specified
+.Tn ELF
+.Ar file .
+.Pp
+The options are as follows:
+.Bl -tag -width ".Fl w Ar file"
+.It Fl a
+Dump all information.
+.It Fl c
+Dump section headers.
+.It Fl d
+Dump dynamic symbols.
+.It Fl e
+Dump ELF header.
+.It Fl G
+Dump the GOT.
+.It Fl h
+Dump the hash values.
+.It Fl i
+Dump the dynamic interpreter.
+.It Fl k
+Dump the ELF checksum.
+.It Fl n
+Dump note sections.
+.It Fl N Ar name
+Only dump the section with the specific
+.Ar name .
+Archive symbol table can be specified with
+the special section name ARSYM.
+More than one
+.Fl N
+option may appear.
+.It Fl p
+Dump the program header.
+.It Fl r
+Dump relocations.
+.It Fl s
+Dump the symbol table.
+.It Fl S
+Output in the Solaris
+.Nm
+format.
+.It Fl v
+Dump the symbol-versioning sections.
+.It Fl V
+Print a version identifier and exit.
+.It Fl w Ar file
+Write output to a
+.Ar file
+instead of the standard output.
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+The following is an example of a typical usage
+of the
+.Nm
+command:
+.Pp
+.Dl "elfdump -a -w output /bin/ls"
+.Pp
+To dump the content of '.dynsym' symbol table:
+.Pp
+.Dl "elfdump -s -N .dynsym /bin/ls"
+.Pp
+To dump the archive symbol table,
+but not the symbol tables of archive members:
+.Pp
+.Dl "elfdump -s -N ARSYM /usr/lib/libelf.a"
+.Pp
+To dump the content of .got section and
+the symbol-versioning sections in Solaris
+.Nm
+format:
+.Pp
+.Dl "elfdump -S -Gv /bin/ls"
+.Sh SEE ALSO
+.Xr objdump 1 ,
+.Xr readelf 1 ,
+.Xr elf 3
+.Rs
+.%A "AT&T Unix Systems Labs"
+.%T "System V Application Binary Interface"
+.%O http://www.sco.com/developers/gabi/
+.Re
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Fx 5.0 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+utility
+was written by
+.An Jake Burkholder Aq Mt jake@FreeBSD.org .
+Later it was rewritten based on the
+libelf library.
+This
+manual page was written by
+.An David O'Brien Aq Mt obrien@FreeBSD.org .
+.Pp
+.An Kai Wang Aq Mt kaiw@FreeBSD.org
+rewrote it using the
+.Lb libelf
+and implemented additional functionality.
+.Sh BUGS
+Does not fully implement the
+.Tn ELF
+gABI.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/elfdump/elfdump.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,2680 @@
+/*-
+ * Copyright (c) 2007-2012 Kai Wang
+ * Copyright (c) 2003 David O'Brien.  All rights reserved.
+ * Copyright (c) 2001 Jake Burkholder
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <ar.h>
+#include <assert.h>
+#include <err.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <getopt.h>
+#include <libelftc.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef USE_LIBARCHIVE_AR
+#include <archive.h>
+#include <archive_entry.h>
+#endif
+
+#include "_elftc.h"
+
+ELFTC_VCSID("$Id: elfdump.c 3584 2017-11-05 20:51:43Z jkoshy $");
+
+#if defined(ELFTC_NEED_ELF_NOTE_DEFINITION)
+#include "native-elf-format.h"
+#if ELFTC_CLASS == ELFCLASS32
+typedef Elf32_Nhdr	Elf_Note;
+#else
+typedef Elf64_Nhdr	Elf_Note;
+#endif
+#endif
+
+/* elfdump(1) options. */
+#define	ED_DYN		(1<<0)
+#define	ED_EHDR		(1<<1)
+#define	ED_GOT		(1<<2)
+#define	ED_HASH		(1<<3)
+#define	ED_INTERP	(1<<4)
+#define	ED_NOTE		(1<<5)
+#define	ED_PHDR		(1<<6)
+#define	ED_REL		(1<<7)
+#define	ED_SHDR		(1<<8)
+#define	ED_SYMTAB	(1<<9)
+#define	ED_SYMVER	(1<<10)
+#define	ED_CHECKSUM	(1<<11)
+#define	ED_ALL		((1<<12)-1)
+
+/* elfdump(1) run control flags. */
+#define	SOLARIS_FMT		(1<<0)
+#define	PRINT_FILENAME		(1<<1)
+#define	PRINT_ARSYM		(1<<2)
+#define	ONLY_ARSYM		(1<<3)
+
+/* Convenient print macro. */
+#define	PRT(...)	fprintf(ed->out, __VA_ARGS__)
+
+/* Internal data structure for sections. */
+struct section {
+	const char	*name;		/* section name */
+	Elf_Scn		*scn;		/* section scn */
+	uint64_t	 off;		/* section offset */
+	uint64_t	 sz;		/* section size */
+	uint64_t	 entsize;	/* section entsize */
+	uint64_t	 align;		/* section alignment */
+	uint64_t	 type;		/* section type */
+	uint64_t	 flags;		/* section flags */
+	uint64_t	 addr;		/* section virtual addr */
+	uint32_t	 link;		/* section link ndx */
+	uint32_t	 info;		/* section info ndx */
+};
+
+struct spec_name {
+	const char	*name;
+	STAILQ_ENTRY(spec_name)	sn_list;
+};
+
+/* Structure encapsulates the global data for readelf(1). */
+struct elfdump {
+	FILE		*out;		/* output redirection. */
+	const char	*filename;	/* current processing file. */
+	const char	*archive;	/* archive name */
+	int		 options;	/* command line options. */
+	int		 flags;		/* run control flags. */
+	Elf		*elf;		/* underlying ELF descriptor. */
+#ifndef USE_LIBARCHIVE_AR
+	Elf		*ar;		/* ar(1) archive descriptor. */
+#endif
+	GElf_Ehdr	 ehdr;		/* ELF header. */
+	int		 ec;		/* ELF class. */
+	size_t		 shnum;		/* #sections. */
+	struct section	*sl;		/* list of sections. */
+	STAILQ_HEAD(, spec_name) snl;	/* list of names specified by -N. */
+};
+
+/* Relocation entry. */
+struct rel_entry {
+	union {
+		GElf_Rel rel;
+		GElf_Rela rela;
+	} u_r;
+	const char *symn;
+	uint32_t type;
+};
+
+#if defined(ELFTC_NEED_BYTEORDER_EXTENSIONS)
+static __inline uint32_t
+be32dec(const void *pp)
+{
+	unsigned char const *p = (unsigned char const *)pp;
+
+	return ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
+}
+
+static __inline uint32_t
+le32dec(const void *pp)
+{
+	unsigned char const *p = (unsigned char const *)pp;
+
+	return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]);
+}
+#endif
+
+/* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#tag_encodings */
+static const char *
+d_tags(uint64_t tag)
+{
+	static char unknown_buf[64];
+
+	switch (tag) {
+	case DT_NULL:		return "DT_NULL";
+	case DT_NEEDED:		return "DT_NEEDED";
+	case DT_PLTRELSZ:	return "DT_PLTRELSZ";
+	case DT_PLTGOT:		return "DT_PLTGOT";
+	case DT_HASH:		return "DT_HASH";
+	case DT_STRTAB:		return "DT_STRTAB";
+	case DT_SYMTAB:		return "DT_SYMTAB";
+	case DT_RELA:		return "DT_RELA";
+	case DT_RELASZ:		return "DT_RELASZ";
+	case DT_RELAENT:	return "DT_RELAENT";
+	case DT_STRSZ:		return "DT_STRSZ";
+	case DT_SYMENT:		return "DT_SYMENT";
+	case DT_INIT:		return "DT_INIT";
+	case DT_FINI:		return "DT_FINI";
+	case DT_SONAME:		return "DT_SONAME";
+	case DT_RPATH:		return "DT_RPATH";
+	case DT_SYMBOLIC:	return "DT_SYMBOLIC";
+	case DT_REL:		return "DT_REL";
+	case DT_RELSZ:		return "DT_RELSZ";
+	case DT_RELENT:		return "DT_RELENT";
+	case DT_PLTREL:		return "DT_PLTREL";
+	case DT_DEBUG:		return "DT_DEBUG";
+	case DT_TEXTREL:	return "DT_TEXTREL";
+	case DT_JMPREL:		return "DT_JMPREL";
+	case DT_BIND_NOW:	return "DT_BIND_NOW";
+	case DT_INIT_ARRAY:	return "DT_INIT_ARRAY";
+	case DT_FINI_ARRAY:	return "DT_FINI_ARRAY";
+	case DT_INIT_ARRAYSZ:	return "DT_INIT_ARRAYSZ";
+	case DT_FINI_ARRAYSZ:	return "DT_FINI_ARRAYSZ";
+	case DT_RUNPATH:	return "DT_RUNPATH";
+	case DT_FLAGS:		return "DT_FLAGS";
+	case DT_PREINIT_ARRAY:	return "DT_PREINIT_ARRAY"; /* XXX DT_ENCODING */
+	case DT_PREINIT_ARRAYSZ:return "DT_PREINIT_ARRAYSZ";
+	/* 0x6000000D - 0x6ffff000 operating system-specific semantics */
+	case 0x6ffffdf5:	return "DT_GNU_PRELINKED";
+	case 0x6ffffdf6:	return "DT_GNU_CONFLICTSZ";
+	case 0x6ffffdf7:	return "DT_GNU_LIBLISTSZ";
+	case 0x6ffffdf8:	return "DT_SUNW_CHECKSUM";
+	case DT_PLTPADSZ:	return "DT_PLTPADSZ";
+	case DT_MOVEENT:	return "DT_MOVEENT";
+	case DT_MOVESZ:		return "DT_MOVESZ";
+	case 0x6ffffdfc:	return "DT_FEATURE";
+	case DT_POSFLAG_1:	return "DT_POSFLAG_1";
+	case DT_SYMINSZ:	return "DT_SYMINSZ";
+	case DT_SYMINENT:	return "DT_SYMINENT (DT_VALRNGHI)";
+	case DT_ADDRRNGLO:	return "DT_ADDRRNGLO";
+	case DT_GNU_HASH:	return "DT_GNU_HASH";
+	case 0x6ffffef8:	return "DT_GNU_CONFLICT";
+	case 0x6ffffef9:	return "DT_GNU_LIBLIST";
+	case 0x6ffffefa:	return "DT_CONFIG";
+	case 0x6ffffefb:	return "DT_DEPAUDIT";
+	case 0x6ffffefc:	return "DT_AUDIT";
+	case 0x6ffffefd:	return "DT_PLTPAD";
+	case 0x6ffffefe:	return "DT_MOVETAB";
+	case DT_SYMINFO:	return "DT_SYMINFO (DT_ADDRRNGHI)";
+	case DT_RELACOUNT:	return "DT_RELACOUNT";
+	case DT_RELCOUNT:	return "DT_RELCOUNT";
+	case DT_FLAGS_1:	return "DT_FLAGS_1";
+	case DT_VERDEF:		return "DT_VERDEF";
+	case DT_VERDEFNUM:	return "DT_VERDEFNUM";
+	case DT_VERNEED:	return "DT_VERNEED";
+	case DT_VERNEEDNUM:	return "DT_VERNEEDNUM";
+	case 0x6ffffff0:	return "DT_GNU_VERSYM";
+	/* 0x70000000 - 0x7fffffff processor-specific semantics */
+	case 0x70000000:	return "DT_IA_64_PLT_RESERVE";
+	case DT_AUXILIARY:	return "DT_AUXILIARY";
+	case DT_USED:		return "DT_USED";
+	case DT_FILTER:		return "DT_FILTER";
+	}
+
+	snprintf(unknown_buf, sizeof(unknown_buf),
+		"<unknown: %#llx>", (unsigned long long)tag);
+	return (unknown_buf);
+}
+
+static const char *
+e_machines(unsigned int mach)
+{
+	static char machdesc[64];
+
+	switch (mach) {
+	case EM_NONE:	return "EM_NONE";
+	case EM_M32:	return "EM_M32";
+	case EM_SPARC:	return "EM_SPARC";
+	case EM_386:	return "EM_386";
+	case EM_68K:	return "EM_68K";
+	case EM_88K:	return "EM_88K";
+	case EM_IAMCU:	return "EM_IAMCU";
+	case EM_860:	return "EM_860";
+	case EM_MIPS:	return "EM_MIPS";
+	case EM_PPC:	return "EM_PPC";
+	case EM_PPC64:	return "EM_PPC64";
+	case EM_ARM:	return "EM_ARM";
+	case EM_ALPHA:	return "EM_ALPHA (legacy)";
+	case EM_SPARCV9:return "EM_SPARCV9";
+	case EM_IA_64:	return "EM_IA_64";
+	case EM_X86_64:	return "EM_X86_64";
+	case EM_AARCH64:return "EM_AARCH64";
+	case EM_RISCV:	return "EM_RISCV";
+	}
+	snprintf(machdesc, sizeof(machdesc),
+	    "(unknown machine) -- type 0x%x", mach);
+	return (machdesc);
+}
+
+static const char *
+elf_type_str(unsigned int type)
+{
+	static char s_type[32];
+
+	switch (type)
+	{
+	case ET_NONE:	return "ET_NONE";
+	case ET_REL:	return "ET_REL";
+	case ET_EXEC:	return "ET_EXEC";
+	case ET_DYN:	return "ET_DYN";
+	case ET_CORE:	return "ET_CORE";
+	}
+	if (type >= ET_LOPROC)
+		snprintf(s_type, sizeof(s_type), "<proc: %#x>", type);
+	else if (type >= ET_LOOS && type <= ET_HIOS)
+		snprintf(s_type, sizeof(s_type), "<os: %#x>", type);
+	else
+		snprintf(s_type, sizeof(s_type), "<unknown: %#x", type);
+	return (s_type);
+}
+
+static const char *
+elf_version_str(unsigned int ver)
+{
+	static char s_ver[32];
+
+	switch (ver) {
+	case EV_NONE:		return "EV_NONE";
+	case EV_CURRENT:	return "EV_CURRENT";
+	}
+	snprintf(s_ver, sizeof(s_ver), "<unknown: %#x>", ver);
+	return (s_ver);
+}
+
+static const char *
+elf_class_str(unsigned int class)
+{
+	static char s_class[32];
+
+	switch (class) {
+	case ELFCLASSNONE:	return "ELFCLASSNONE";
+	case ELFCLASS32:	return "ELFCLASS32";
+	case ELFCLASS64:	return "ELFCLASS64";
+	}
+	snprintf(s_class, sizeof(s_class), "<unknown: %#x>", class);
+	return (s_class);
+}
+
+static const char *
+elf_data_str(unsigned int data)
+{
+	static char s_data[32];
+
+	switch (data) {
+	case ELFDATANONE:	return "ELFDATANONE";
+	case ELFDATA2LSB:	return "ELFDATA2LSB";
+	case ELFDATA2MSB:	return "ELFDATA2MSB";
+	}
+	snprintf(s_data, sizeof(s_data), "<unknown: %#x>", data);
+	return (s_data);
+}
+
+static const char *ei_abis[256] = {
+	"ELFOSABI_NONE", "ELFOSABI_HPUX", "ELFOSABI_NETBSD", "ELFOSABI_LINUX",
+	"ELFOSABI_HURD", "ELFOSABI_86OPEN", "ELFOSABI_SOLARIS", "ELFOSABI_AIX",
+	"ELFOSABI_IRIX", "ELFOSABI_FREEBSD", "ELFOSABI_TRU64",
+	"ELFOSABI_MODESTO", "ELFOSABI_OPENBSD",
+	[17] = "ELFOSABI_CLOUDABI",
+	[64] = "ELFOSABI_ARM_AEABI",
+	[97] = "ELFOSABI_ARM",
+	[255] = "ELFOSABI_STANDALONE"
+};
+
+static const char *
+elf_phdr_type_str(unsigned int type)
+{
+	static char s_type[32];
+
+	switch (type) {
+	case PT_NULL:		return "PT_NULL";
+	case PT_LOAD:		return "PT_LOAD";
+	case PT_DYNAMIC:	return "PT_DYNAMIC";
+	case PT_INTERP:		return "PT_INTERP";
+	case PT_NOTE:		return "PT_NOTE";
+	case PT_SHLIB:		return "PT_SHLIB";
+	case PT_PHDR:		return "PT_PHDR";
+	case PT_TLS:		return "PT_TLS";
+	case PT_GNU_EH_FRAME:	return "PT_GNU_EH_FRAME";
+	case PT_GNU_STACK:	return "PT_GNU_STACK";
+	case PT_GNU_RELRO:	return "PT_GNU_RELRO";
+	}
+	snprintf(s_type, sizeof(s_type), "<unknown: %#x>", type);
+	return (s_type);
+}
+
+static const char *p_flags[] = {
+	"", "PF_X", "PF_W", "PF_X|PF_W", "PF_R", "PF_X|PF_R", "PF_W|PF_R",
+	"PF_X|PF_W|PF_R"
+};
+
+static const char *
+sh_name(struct elfdump *ed, int ndx)
+{
+	static char num[10];
+
+	switch (ndx) {
+	case SHN_UNDEF: return "UNDEF";
+	case SHN_ABS: return "ABS";
+	case SHN_COMMON: return "COMMON";
+	default:
+		if ((uint64_t)ndx < ed->shnum)
+			return (ed->sl[ndx].name);
+		else {
+			snprintf(num, sizeof(num), "%d", ndx);
+			return (num);
+		}
+	}
+}
+
+/* http://www.sco.com/developers/gabi/latest/ch4.sheader.html#sh_type */
+static const char *
+sh_types(uint64_t mach, uint64_t sht) {
+	static char unknown_buf[64];
+
+	if (sht < 0x60000000) {
+		switch (sht) {
+		case SHT_NULL:		return "SHT_NULL";
+		case SHT_PROGBITS:	return "SHT_PROGBITS";
+		case SHT_SYMTAB:	return "SHT_SYMTAB";
+		case SHT_STRTAB:	return "SHT_STRTAB";
+		case SHT_RELA:		return "SHT_RELA";
+		case SHT_HASH:		return "SHT_HASH";
+		case SHT_DYNAMIC:	return "SHT_DYNAMIC";
+		case SHT_NOTE:		return "SHT_NOTE";
+		case SHT_NOBITS:	return "SHT_NOBITS";
+		case SHT_REL:		return "SHT_REL";
+		case SHT_SHLIB:		return "SHT_SHLIB";
+		case SHT_DYNSYM:	return "SHT_DYNSYM";
+		case SHT_INIT_ARRAY:	return "SHT_INIT_ARRAY";
+		case SHT_FINI_ARRAY:	return "SHT_FINI_ARRAY";
+		case SHT_PREINIT_ARRAY:	return "SHT_PREINIT_ARRAY";
+		case SHT_GROUP:		return "SHT_GROUP";
+		case SHT_SYMTAB_SHNDX:	return "SHT_SYMTAB_SHNDX";
+		}
+	} else if (sht < 0x70000000) {
+		/* 0x60000000-0x6fffffff operating system-specific semantics */
+		switch (sht) {
+		case 0x6ffffff0:	return "XXX:VERSYM";
+		case SHT_SUNW_dof:	return "SHT_SUNW_dof";
+		case SHT_GNU_HASH:	return "SHT_GNU_HASH";
+		case 0x6ffffff7:	return "SHT_GNU_LIBLIST";
+		case 0x6ffffffc:	return "XXX:VERDEF";
+		case SHT_SUNW_verdef:	return "SHT_SUNW(GNU)_verdef";
+		case SHT_SUNW_verneed:	return "SHT_SUNW(GNU)_verneed";
+		case SHT_SUNW_versym:	return "SHT_SUNW(GNU)_versym";
+		}
+	} else if (sht < 0x80000000) {
+		/* 0x70000000 - 0x7fffffff processor-specific semantics */
+		switch (mach) {
+		case EM_ARM:
+			switch (sht) {
+			case SHT_ARM_EXIDX: return "SHT_ARM_EXIDX";
+			case SHT_ARM_PREEMPTMAP: return "SHT_ARM_PREEMPTMAP";
+			case SHT_ARM_ATTRIBUTES: return "SHT_ARM_ATTRIBUTES";
+			case SHT_ARM_DEBUGOVERLAY:
+			    return "SHT_ARM_DEBUGOVERLAY";
+			case SHT_ARM_OVERLAYSECTION:
+			    return "SHT_ARM_OVERLAYSECTION";
+			}
+			break;
+		case EM_IA_64:
+			switch (sht) {
+			case 0x70000000: return "SHT_IA_64_EXT";
+			case 0x70000001: return "SHT_IA_64_UNWIND";
+			}
+			break;
+		case EM_MIPS:
+			switch (sht) {
+			case SHT_MIPS_REGINFO: return "SHT_MIPS_REGINFO";
+			case SHT_MIPS_OPTIONS: return "SHT_MIPS_OPTIONS";
+			case SHT_MIPS_ABIFLAGS: return "SHT_MIPS_ABIFLAGS";
+			}
+			break;
+		}
+		switch (sht) {
+		case 0x7ffffffd: return "XXX:AUXILIARY";
+		case 0x7fffffff: return "XXX:FILTER";
+		}
+	}
+	/* 0x80000000 - 0xffffffff application programs */
+
+	snprintf(unknown_buf, sizeof(unknown_buf),
+		"<unknown: %#llx>", (unsigned long long)sht);
+	return (unknown_buf);
+}
+
+/*
+ * Define known section flags. These flags are defined in the order
+ * they are to be printed out.
+ */
+#define	DEFINE_SHFLAGS()			\
+	DEFINE_SHF(WRITE)			\
+	DEFINE_SHF(ALLOC)			\
+	DEFINE_SHF(EXECINSTR)			\
+	DEFINE_SHF(MERGE)			\
+	DEFINE_SHF(STRINGS)			\
+	DEFINE_SHF(INFO_LINK)			\
+	DEFINE_SHF(LINK_ORDER)			\
+	DEFINE_SHF(OS_NONCONFORMING)		\
+	DEFINE_SHF(GROUP)			\
+	DEFINE_SHF(TLS)				\
+	DEFINE_SHF(COMPRESSED)
+
+#undef	DEFINE_SHF
+#define	DEFINE_SHF(F) "SHF_" #F "|"
+#define ALLSHFLAGS	DEFINE_SHFLAGS()
+
+static const char *
+sh_flags(uint64_t shf)
+{
+	static char	flg[sizeof(ALLSHFLAGS)+1];
+
+	flg[0] = '\0';
+
+#undef	DEFINE_SHF
+#define	DEFINE_SHF(N)				\
+	if (shf & SHF_##N)			\
+		strcat(flg, "SHF_" #N "|");	\
+
+	DEFINE_SHFLAGS()
+
+	flg[strlen(flg) - 1] = '\0'; /* Remove the trailing "|". */
+
+	return (flg);
+}
+
+static const char *
+st_type(unsigned int mach, unsigned int type)
+{
+	static char s_type[32];
+
+	switch (type) {
+	case STT_NOTYPE: return "STT_NOTYPE";
+	case STT_OBJECT: return "STT_OBJECT";
+	case STT_FUNC: return "STT_FUNC";
+	case STT_SECTION: return "STT_SECTION";
+	case STT_FILE: return "STT_FILE";
+	case STT_COMMON: return "STT_COMMON";
+	case STT_TLS: return "STT_TLS";
+	case 13:
+		if (mach == EM_SPARCV9)
+			return "STT_SPARC_REGISTER";
+		break;
+	}
+	snprintf(s_type, sizeof(s_type), "<unknown: %#x>", type);
+	return (s_type);
+}
+
+static const char *
+st_type_S(unsigned int type)
+{
+	static char s_type[32];
+
+	switch (type) {
+	case STT_NOTYPE: return "NOTY";
+	case STT_OBJECT: return "OBJT";
+	case STT_FUNC: return "FUNC";
+	case STT_SECTION: return "SECT";
+	case STT_FILE: return "FILE";
+	}
+	snprintf(s_type, sizeof(s_type), "<unknown: %#x>", type);
+	return (s_type);
+}
+
+static const char *
+st_bindings(unsigned int sbind)
+{
+	static char s_sbind[32];
+
+	switch (sbind) {
+	case STB_LOCAL: return "STB_LOCAL";
+	case STB_GLOBAL: return "STB_GLOBAL";
+	case STB_WEAK: return "STB_WEAK";
+	case STB_GNU_UNIQUE: return "STB_GNU_UNIQUE";
+	default:
+		if (sbind >= STB_LOOS && sbind <= STB_HIOS)
+			return "OS";
+		else if (sbind >= STB_LOPROC && sbind <= STB_HIPROC)
+			return "PROC";
+		else
+			snprintf(s_sbind, sizeof(s_sbind), "<unknown: %#x>",
+			    sbind);
+		return (s_sbind);
+	}
+}
+
+static const char *
+st_bindings_S(unsigned int sbind)
+{
+	static char s_sbind[32];
+
+	switch (sbind) {
+	case STB_LOCAL: return "LOCL";
+	case STB_GLOBAL: return "GLOB";
+	case STB_WEAK: return "WEAK";
+	case STB_GNU_UNIQUE: return "UNIQ";
+	default:
+		if (sbind >= STB_LOOS && sbind <= STB_HIOS)
+			return "OS";
+		else if (sbind >= STB_LOPROC && sbind <= STB_HIPROC)
+			return "PROC";
+		else
+			snprintf(s_sbind, sizeof(s_sbind), "<%#x>",
+			    sbind);
+		return (s_sbind);
+	}
+}
+
+static unsigned char st_others[] = {
+	'D', 'I', 'H', 'P'
+};
+
+static void	add_name(struct elfdump *ed, const char *name);
+static void	elf_print_object(struct elfdump *ed);
+static void	elf_print_elf(struct elfdump *ed);
+static void	elf_print_ehdr(struct elfdump *ed);
+static void	elf_print_phdr(struct elfdump *ed);
+static void	elf_print_shdr(struct elfdump *ed);
+static void	elf_print_symtab(struct elfdump *ed, int i);
+static void	elf_print_symtabs(struct elfdump *ed);
+static void	elf_print_symver(struct elfdump *ed);
+static void	elf_print_verdef(struct elfdump *ed, struct section *s);
+static void	elf_print_verneed(struct elfdump *ed, struct section *s);
+static void	elf_print_interp(struct elfdump *ed);
+static void	elf_print_dynamic(struct elfdump *ed);
+static void	elf_print_rel_entry(struct elfdump *ed, struct section *s,
+    int j, struct rel_entry *r);
+static void	elf_print_rela(struct elfdump *ed, struct section *s,
+    Elf_Data *data);
+static void	elf_print_rel(struct elfdump *ed, struct section *s,
+    Elf_Data *data);
+static void	elf_print_reloc(struct elfdump *ed);
+static void	elf_print_got(struct elfdump *ed);
+static void	elf_print_got_section(struct elfdump *ed, struct section *s);
+static void	elf_print_note(struct elfdump *ed);
+static void	elf_print_svr4_hash(struct elfdump *ed, struct section *s);
+static void	elf_print_svr4_hash64(struct elfdump *ed, struct section *s);
+static void	elf_print_gnu_hash(struct elfdump *ed, struct section *s);
+static void	elf_print_hash(struct elfdump *ed);
+static void	elf_print_checksum(struct elfdump *ed);
+static void	find_gotrel(struct elfdump *ed, struct section *gs,
+    struct rel_entry *got);
+static struct spec_name	*find_name(struct elfdump *ed, const char *name);
+static int	get_ent_count(const struct section *s, int *ent_count);
+static const char *get_symbol_name(struct elfdump *ed, uint32_t symtab, int i);
+static const char *get_string(struct elfdump *ed, int strtab, size_t off);
+static void	get_versym(struct elfdump *ed, int i, uint16_t **vs, int *nvs);
+static void	load_sections(struct elfdump *ed);
+static void	unload_sections(struct elfdump *ed);
+static void	usage(void);
+#ifdef	USE_LIBARCHIVE_AR
+static int	ac_detect_ar(int fd);
+static void	ac_print_ar(struct elfdump *ed, int fd);
+#else
+static void	elf_print_ar(struct elfdump *ed, int fd);
+#endif	/* USE_LIBARCHIVE_AR */
+
+static struct option elfdump_longopts[] =
+{
+	{ "help",	no_argument,	NULL,	'H' },
+	{ "version",	no_argument,	NULL,	'V' },
+	{ NULL,		0,		NULL,	0   }
+};
+
+int
+main(int ac, char **av)
+{
+	struct elfdump		*ed, ed_storage;
+	struct spec_name	*sn;
+	int			 ch, i;
+
+	ed = &ed_storage;
+	memset(ed, 0, sizeof(*ed));
+	STAILQ_INIT(&ed->snl);
+	ed->out = stdout;
+	while ((ch = getopt_long(ac, av, "acdeiGHhknN:prsSvVw:",
+		elfdump_longopts, NULL)) != -1)
+		switch (ch) {
+		case 'a':
+			ed->options = ED_ALL;
+			break;
+		case 'c':
+			ed->options |= ED_SHDR;
+			break;
+		case 'd':
+			ed->options |= ED_DYN;
+			break;
+		case 'e':
+			ed->options |= ED_EHDR;
+			break;
+		case 'i':
+			ed->options |= ED_INTERP;
+			break;
+		case 'G':
+			ed->options |= ED_GOT;
+			break;
+		case 'h':
+			ed->options |= ED_HASH;
+			break;
+		case 'k':
+			ed->options |= ED_CHECKSUM;
+			break;
+		case 'n':
+			ed->options |= ED_NOTE;
+			break;
+		case 'N':
+			add_name(ed, optarg);
+			break;
+		case 'p':
+			ed->options |= ED_PHDR;
+			break;
+		case 'r':
+			ed->options |= ED_REL;
+			break;
+		case 's':
+			ed->options |= ED_SYMTAB;
+			break;
+		case 'S':
+			ed->flags |= SOLARIS_FMT;
+			break;
+		case 'v':
+			ed->options |= ED_SYMVER;
+			break;
+		case 'V':
+			(void) printf("%s (%s)\n", ELFTC_GETPROGNAME(),
+			    elftc_version());
+			exit(EXIT_SUCCESS);
+			break;
+		case 'w':
+			if ((ed->out = fopen(optarg, "w")) == NULL)
+				err(EXIT_FAILURE, "%s", optarg);
+			break;
+		case '?':
+		case 'H':
+		default:
+			usage();
+		}
+
+	ac -= optind;
+	av += optind;
+
+	if (ed->options == 0)
+		ed->options = ED_ALL;
+	sn = NULL;
+	if (ed->options & ED_SYMTAB &&
+	    (STAILQ_EMPTY(&ed->snl) || (sn = find_name(ed, "ARSYM")) != NULL)) {
+		ed->flags |= PRINT_ARSYM;
+		if (sn != NULL) {
+			STAILQ_REMOVE(&ed->snl, sn, spec_name, sn_list);
+			if (STAILQ_EMPTY(&ed->snl))
+				ed->flags |= ONLY_ARSYM;
+		}
+	}
+	if (ac == 0)
+		usage();
+	if (ac > 1)
+		ed->flags |= PRINT_FILENAME;
+	if (elf_version(EV_CURRENT) == EV_NONE)
+		errx(EXIT_FAILURE, "ELF library initialization failed: %s",
+		    elf_errmsg(-1));
+
+	for (i = 0; i < ac; i++) {
+		ed->filename = av[i];
+		ed->archive = NULL;
+		elf_print_object(ed);
+	}
+
+	exit(EXIT_SUCCESS);
+}
+
+#ifdef USE_LIBARCHIVE_AR
+
+/* Archive symbol table entry. */
+struct arsym_entry {
+	char *sym_name;
+	size_t off;
+};
+
+/*
+ * Convenient wrapper for general libarchive error handling.
+ */
+#define	AC(CALL) do {							\
+	if ((CALL)) {							\
+		warnx("%s", archive_error_string(a));			\
+		return;							\
+	}								\
+} while (0)
+
+/*
+ * Detect an ar(1) archive using libarchive(3).
+ */
+static int
+ac_detect_ar(int fd)
+{
+	struct archive		*a;
+	struct archive_entry	*entry;
+	int			 r;
+
+	r = -1;
+	if ((a = archive_read_new()) == NULL)
+		return (0);
+	archive_read_support_format_ar(a);
+	if (archive_read_open_fd(a, fd, 10240) == ARCHIVE_OK)
+		r = archive_read_next_header(a, &entry);
+	archive_read_close(a);
+	archive_read_free(a);
+
+	return (r == ARCHIVE_OK);
+}
+
+/*
+ * Dump an ar(1) archive using libarchive(3).
+ */
+static void
+ac_print_ar(struct elfdump *ed, int fd)
+{
+	struct archive		*a;
+	struct archive_entry	*entry;
+	struct arsym_entry	*arsym;
+	const char		*name;
+	char			 idx[10], *b;
+	void			*buff;
+	size_t			 size;
+	uint32_t		 cnt, i;
+	int			 r;
+
+	if (lseek(fd, 0, SEEK_SET) == -1)
+		err(EXIT_FAILURE, "lseek failed");
+	if ((a = archive_read_new()) == NULL)
+		errx(EXIT_FAILURE, "%s", archive_error_string(a));
+	archive_read_support_format_ar(a);
+	AC(archive_read_open_fd(a, fd, 10240));
+	for(;;) {
+		r = archive_read_next_header(a, &entry);
+		if (r == ARCHIVE_FATAL)
+			errx(EXIT_FAILURE, "%s", archive_error_string(a));
+		if (r == ARCHIVE_EOF)
+			break;
+		if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY)
+			warnx("%s", archive_error_string(a));
+		if (r == ARCHIVE_RETRY)
+			continue;
+		name = archive_entry_pathname(entry);
+		size = archive_entry_size(entry);
+		if (size == 0)
+			continue;
+		if ((buff = malloc(size)) == NULL) {
+			warn("malloc failed");
+			continue;
+		}
+		if (archive_read_data(a, buff, size) != (ssize_t)size) {
+			warnx("%s", archive_error_string(a));
+			free(buff);
+			continue;
+		}
+
+		/*
+		 * Note that when processing arsym via libarchive, there is
+		 * no way to tell which member a certain symbol belongs to,
+		 * since we can not just "lseek" to a member offset and read
+		 * the member header.
+		 */
+		if (!strcmp(name, "/") && ed->flags & PRINT_ARSYM) {
+			b = buff;
+			cnt = be32dec(b);
+			if (cnt == 0) {
+				free(buff);
+				continue;
+			}
+			arsym = calloc(cnt, sizeof(*arsym));
+			if (arsym == NULL)
+				err(EXIT_FAILURE, "calloc failed");
+			b += sizeof(uint32_t);
+			for (i = 0; i < cnt; i++) {
+				arsym[i].off = be32dec(b);
+				b += sizeof(uint32_t);
+			}
+			for (i = 0; i < cnt; i++) {
+				arsym[i].sym_name = b;
+				b += strlen(b) + 1;
+			}
+			if (ed->flags & SOLARIS_FMT) {
+				PRT("\nSymbol Table: (archive)\n");
+				PRT("     index    offset    symbol\n");
+			} else
+				PRT("\nsymbol table (archive):\n");
+			for (i = 0; i < cnt; i++) {
+				if (ed->flags & SOLARIS_FMT) {
+					snprintf(idx, sizeof(idx), "[%d]", i);
+					PRT("%10s  ", idx);
+					PRT("0x%8.8jx  ",
+					    (uintmax_t)arsym[i].off);
+					PRT("%s\n", arsym[i].sym_name);
+				} else {
+					PRT("\nentry: %d\n", i);
+					PRT("\toffset: %#jx\n",
+					    (uintmax_t)arsym[i].off);
+					PRT("\tsymbol: %s\n",
+					    arsym[i].sym_name);
+				}
+			}
+			free(arsym);
+			free(buff);
+			/* No need to continue if we only dump ARSYM. */
+			if (ed->flags & ONLY_ARSYM) {
+				AC(archive_read_close(a));
+				AC(archive_read_free(a));
+				return;
+			}
+			continue;
+		}
+		if ((ed->elf = elf_memory(buff, size)) == NULL) {
+			warnx("elf_memroy() failed: %s",
+			      elf_errmsg(-1));
+			free(buff);
+			continue;
+		}
+		/* Skip non-ELF member. */
+		if (elf_kind(ed->elf) == ELF_K_ELF) {
+			printf("\n%s(%s):\n", ed->archive, name);
+			elf_print_elf(ed);
+		}
+		elf_end(ed->elf);
+		free(buff);
+	}
+	AC(archive_read_close(a));
+	AC(archive_read_free(a));
+}
+
+#else  /* USE_LIBARCHIVE_AR */
+
+/*
+ * Dump an ar(1) archive.
+ */
+static void
+elf_print_ar(struct elfdump *ed, int fd)
+{
+	Elf		*e;
+	Elf_Arhdr	*arh;
+	Elf_Arsym	*arsym;
+	Elf_Cmd		 cmd;
+	char		 idx[21];
+	size_t		 cnt, i;
+
+	ed->ar = ed->elf;
+
+	if (ed->flags & PRINT_ARSYM) {
+		cnt = 0;
+		if ((arsym = elf_getarsym(ed->ar, &cnt)) == NULL) {
+			warnx("elf_getarsym failed: %s", elf_errmsg(-1));
+			goto print_members;
+		}
+		if (cnt == 0)
+			goto print_members;
+		if (ed->flags & SOLARIS_FMT) {
+			PRT("\nSymbol Table: (archive)\n");
+			PRT("     index    offset    member name and symbol\n");
+		} else
+			PRT("\nsymbol table (archive):\n");
+		for (i = 0; i < cnt - 1; i++) {
+			if (elf_rand(ed->ar, arsym[i].as_off) !=
+			    arsym[i].as_off) {
+				warnx("elf_rand failed: %s", elf_errmsg(-1));
+				break;
+			}
+			if ((e = elf_begin(fd, ELF_C_READ, ed->ar)) == NULL) {
+				warnx("elf_begin failed: %s", elf_errmsg(-1));
+				break;
+			}
+			if ((arh = elf_getarhdr(e)) == NULL) {
+				warnx("elf_getarhdr failed: %s",
+				    elf_errmsg(-1));
+				break;
+			}
+			if (ed->flags & SOLARIS_FMT) {
+				snprintf(idx, sizeof(idx), "[%zu]", i);
+				PRT("%10s  ", idx);
+				PRT("0x%8.8jx  ",
+				    (uintmax_t)arsym[i].as_off);
+				PRT("(%s):%s\n", arh->ar_name,
+				    arsym[i].as_name);
+			} else {
+				PRT("\nentry: %zu\n", i);
+				PRT("\toffset: %#jx\n",
+				    (uintmax_t)arsym[i].as_off);
+				PRT("\tmember: %s\n", arh->ar_name);
+				PRT("\tsymbol: %s\n", arsym[i].as_name);
+			}
+			elf_end(e);
+		}
+
+		/* No need to continue if we only dump ARSYM. */
+		if (ed->flags & ONLY_ARSYM)
+			return;
+	}
+
+print_members:
+
+	/* Rewind the archive. */
+	if (elf_rand(ed->ar, SARMAG) != SARMAG) {
+		warnx("elf_rand failed: %s", elf_errmsg(-1));
+		return;
+	}
+
+	/* Dump each member of the archive. */
+	cmd = ELF_C_READ;
+	while ((ed->elf = elf_begin(fd, cmd, ed->ar)) != NULL) {
+		/* Skip non-ELF member. */
+		if (elf_kind(ed->elf) == ELF_K_ELF) {
+			if ((arh = elf_getarhdr(ed->elf)) == NULL) {
+				warnx("elf_getarhdr failed: %s",
+				    elf_errmsg(-1));
+				break;
+			}
+			printf("\n%s(%s):\n", ed->archive, arh->ar_name);
+			elf_print_elf(ed);
+		}
+		cmd = elf_next(ed->elf);
+		elf_end(ed->elf);
+	}
+}
+
+#endif	/* USE_LIBARCHIVE_AR */
+
+/*
+ * Dump an object. (ELF object or ar(1) archive)
+ */
+static void
+elf_print_object(struct elfdump *ed)
+{
+	int fd;
+
+	if ((fd = open(ed->filename, O_RDONLY)) == -1) {
+		warn("open %s failed", ed->filename);
+		return;
+	}
+
+#ifdef	USE_LIBARCHIVE_AR
+	if (ac_detect_ar(fd)) {
+		ed->archive = ed->filename;
+		ac_print_ar(ed, fd);
+		return;
+	}
+#endif	/* USE_LIBARCHIVE_AR */
+
+	if ((ed->elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
+		warnx("elf_begin() failed: %s", elf_errmsg(-1));
+		return;
+	}
+
+	switch (elf_kind(ed->elf)) {
+	case ELF_K_NONE:
+		warnx("Not an ELF file.");
+		return;
+	case ELF_K_ELF:
+		if (ed->flags & PRINT_FILENAME)
+			printf("\n%s:\n", ed->filename);
+		elf_print_elf(ed);
+		break;
+	case ELF_K_AR:
+#ifndef	USE_LIBARCHIVE_AR
+		ed->archive = ed->filename;
+		elf_print_ar(ed, fd);
+#endif
+		break;
+	default:
+		warnx("Internal: libelf returned unknown elf kind.");
+		return;
+	}
+
+	elf_end(ed->elf);
+}
+
+/*
+ * Dump an ELF object.
+ */
+static void
+elf_print_elf(struct elfdump *ed)
+{
+
+	if (gelf_getehdr(ed->elf, &ed->ehdr) == NULL) {
+		warnx("gelf_getehdr failed: %s", elf_errmsg(-1));
+		return;
+	}
+	if ((ed->ec = gelf_getclass(ed->elf)) == ELFCLASSNONE) {
+		warnx("gelf_getclass failed: %s", elf_errmsg(-1));
+		return;
+	}
+
+	if (ed->options & (ED_SHDR | ED_DYN | ED_REL | ED_GOT | ED_SYMTAB |
+	    ED_SYMVER | ED_NOTE | ED_HASH))
+		load_sections(ed);
+
+	if (ed->options & ED_EHDR)
+		elf_print_ehdr(ed);
+	if (ed->options & ED_PHDR)
+		elf_print_phdr(ed);
+	if (ed->options & ED_INTERP)
+		elf_print_interp(ed);
+	if (ed->options & ED_SHDR)
+		elf_print_shdr(ed);
+	if (ed->options & ED_DYN)
+		elf_print_dynamic(ed);
+	if (ed->options & ED_REL)
+		elf_print_reloc(ed);
+	if (ed->options & ED_GOT)
+		elf_print_got(ed);
+	if (ed->options & ED_SYMTAB)
+		elf_print_symtabs(ed);
+	if (ed->options & ED_SYMVER)
+		elf_print_symver(ed);
+	if (ed->options & ED_NOTE)
+		elf_print_note(ed);
+	if (ed->options & ED_HASH)
+		elf_print_hash(ed);
+	if (ed->options & ED_CHECKSUM)
+		elf_print_checksum(ed);
+
+	unload_sections(ed);
+}
+
+/*
+ * Read the section headers from ELF object and store them in the
+ * internal cache.
+ */
+static void
+load_sections(struct elfdump *ed)
+{
+	struct section	*s;
+	const char	*name;
+	Elf_Scn		*scn;
+	GElf_Shdr	 sh;
+	size_t		 shstrndx, ndx;
+	int		 elferr;
+
+	assert(ed->sl == NULL);
+
+	if (!elf_getshnum(ed->elf, &ed->shnum)) {
+		warnx("elf_getshnum failed: %s", elf_errmsg(-1));
+		return;
+	}
+	if (ed->shnum == 0)
+		return;
+	if ((ed->sl = calloc(ed->shnum, sizeof(*ed->sl))) == NULL)
+		err(EXIT_FAILURE, "calloc failed");
+	if (!elf_getshstrndx(ed->elf, &shstrndx)) {
+		warnx("elf_getshstrndx failed: %s", elf_errmsg(-1));
+		return;
+	}
+	if ((scn = elf_getscn(ed->elf, 0)) == NULL) {
+		warnx("elf_getscn failed: %s", elf_errmsg(-1));
+		return;
+	}
+	(void) elf_errno();
+	do {
+		if (gelf_getshdr(scn, &sh) == NULL) {
+			warnx("gelf_getshdr failed: %s", elf_errmsg(-1));
+			(void) elf_errno();
+			continue;
+		}
+		if ((name = elf_strptr(ed->elf, shstrndx, sh.sh_name)) == NULL) {
+			(void) elf_errno();
+			name = "ERROR";
+		}
+		if ((ndx = elf_ndxscn(scn)) == SHN_UNDEF)
+			if ((elferr = elf_errno()) != 0) {
+				warnx("elf_ndxscn failed: %s",
+				    elf_errmsg(elferr));
+				continue;
+			}
+		if (ndx >= ed->shnum) {
+			warnx("section index of '%s' out of range", name);
+			continue;
+		}
+		s = &ed->sl[ndx];
+		s->name = name;
+		s->scn = scn;
+		s->off = sh.sh_offset;
+		s->sz = sh.sh_size;
+		s->entsize = sh.sh_entsize;
+		s->align = sh.sh_addralign;
+		s->type = sh.sh_type;
+		s->flags = sh.sh_flags;
+		s->addr = sh.sh_addr;
+		s->link = sh.sh_link;
+		s->info = sh.sh_info;
+	} while ((scn = elf_nextscn(ed->elf, scn)) != NULL);
+	elferr = elf_errno();
+	if (elferr != 0)
+		warnx("elf_nextscn failed: %s", elf_errmsg(elferr));
+}
+
+/*
+ * Release section related resources.
+ */
+static void
+unload_sections(struct elfdump *ed)
+{
+	if (ed->sl != NULL) {
+		free(ed->sl);
+		ed->sl = NULL;
+	}
+}
+
+/*
+ * Add a name to the '-N' name list.
+ */
+static void
+add_name(struct elfdump *ed, const char *name)
+{
+	struct spec_name *sn;
+
+	if (find_name(ed, name))
+		return;
+	if ((sn = malloc(sizeof(*sn))) == NULL) {
+		warn("malloc failed");
+		return;
+	}
+	sn->name = name;
+	STAILQ_INSERT_TAIL(&ed->snl, sn, sn_list);
+}
+
+/*
+ * Lookup a name in the '-N' name list.
+ */
+static struct spec_name *
+find_name(struct elfdump *ed, const char *name)
+{
+	struct spec_name *sn;
+
+	STAILQ_FOREACH(sn, &ed->snl, sn_list) {
+		if (!strcmp(sn->name, name))
+			return (sn);
+	}
+
+	return (NULL);
+}
+
+/*
+ * Retrieve the name of a symbol using the section index of the symbol
+ * table and the index of the symbol within that table.
+ */
+static const char *
+get_symbol_name(struct elfdump *ed, uint32_t symtab, int i)
+{
+	static char	 sname[64];
+	struct section	*s;
+	const char	*name;
+	GElf_Sym	 sym;
+	Elf_Data	*data;
+	int		 elferr;
+
+	if (symtab >= ed->shnum)
+		return ("");
+	s = &ed->sl[symtab];
+	if (s->type != SHT_SYMTAB && s->type != SHT_DYNSYM)
+		return ("");
+	(void) elf_errno();
+	if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_getdata failed: %s", elf_errmsg(elferr));
+		return ("");
+	}
+	if (gelf_getsym(data, i, &sym) != &sym)
+		return ("");
+	if (GELF_ST_TYPE(sym.st_info) == STT_SECTION) {
+		if (sym.st_shndx < ed->shnum) {
+			snprintf(sname, sizeof(sname), "%s (section)",
+			    ed->sl[sym.st_shndx].name);
+			return (sname);
+		} else
+			return ("");
+	}
+	if ((name = elf_strptr(ed->elf, s->link, sym.st_name)) == NULL)
+		return ("");
+
+	return (name);
+}
+
+/*
+ * Retrieve a string using string table section index and the string offset.
+ */
+static const char*
+get_string(struct elfdump *ed, int strtab, size_t off)
+{
+	const char *name;
+
+	if ((name = elf_strptr(ed->elf, strtab, off)) == NULL)
+		return ("");
+
+	return (name);
+}
+
+/*
+ * Dump the ELF Executable Header.
+ */
+static void
+elf_print_ehdr(struct elfdump *ed)
+{
+
+	if (!STAILQ_EMPTY(&ed->snl))
+		return;
+
+	if (ed->flags & SOLARIS_FMT) {
+		PRT("\nELF Header\n");
+		PRT("  ei_magic:   { %#x, %c, %c, %c }\n",
+		    ed->ehdr.e_ident[0], ed->ehdr.e_ident[1],
+		    ed->ehdr.e_ident[2], ed->ehdr.e_ident[3]);
+		PRT("  ei_class:   %-18s",
+		    elf_class_str(ed->ehdr.e_ident[EI_CLASS]));
+		PRT("  ei_data:      %s\n",
+		    elf_data_str(ed->ehdr.e_ident[EI_DATA]));
+		PRT("  e_machine:  %-18s", e_machines(ed->ehdr.e_machine));
+		PRT("  e_version:    %s\n",
+		    elf_version_str(ed->ehdr.e_version));
+		PRT("  e_type:     %s\n", elf_type_str(ed->ehdr.e_type));
+		PRT("  e_flags:    %18d\n", ed->ehdr.e_flags);
+		PRT("  e_entry:    %#18jx", (uintmax_t)ed->ehdr.e_entry);
+		PRT("  e_ehsize: %6d", ed->ehdr.e_ehsize);
+		PRT("  e_shstrndx:%5d\n", ed->ehdr.e_shstrndx);
+		PRT("  e_shoff:    %#18jx", (uintmax_t)ed->ehdr.e_shoff);
+		PRT("  e_shentsize: %3d", ed->ehdr.e_shentsize);
+		PRT("  e_shnum:   %5d\n", ed->ehdr.e_shnum);
+		PRT("  e_phoff:    %#18jx", (uintmax_t)ed->ehdr.e_phoff);
+		PRT("  e_phentsize: %3d", ed->ehdr.e_phentsize);
+		PRT("  e_phnum:   %5d\n", ed->ehdr.e_phnum);
+	} else {
+		PRT("\nelf header:\n");
+		PRT("\n");
+		PRT("\te_ident: %s %s %s\n",
+		    elf_class_str(ed->ehdr.e_ident[EI_CLASS]),
+		    elf_data_str(ed->ehdr.e_ident[EI_DATA]),
+		    ei_abis[ed->ehdr.e_ident[EI_OSABI]]);
+		PRT("\te_type: %s\n", elf_type_str(ed->ehdr.e_type));
+		PRT("\te_machine: %s\n", e_machines(ed->ehdr.e_machine));
+		PRT("\te_version: %s\n", elf_version_str(ed->ehdr.e_version));
+		PRT("\te_entry: %#jx\n", (uintmax_t)ed->ehdr.e_entry);
+		PRT("\te_phoff: %ju\n", (uintmax_t)ed->ehdr.e_phoff);
+		PRT("\te_shoff: %ju\n", (uintmax_t) ed->ehdr.e_shoff);
+		PRT("\te_flags: %u\n", ed->ehdr.e_flags);
+		PRT("\te_ehsize: %u\n", ed->ehdr.e_ehsize);
+		PRT("\te_phentsize: %u\n", ed->ehdr.e_phentsize);
+		PRT("\te_phnum: %u\n", ed->ehdr.e_phnum);
+		PRT("\te_shentsize: %u\n", ed->ehdr.e_shentsize);
+		PRT("\te_shnum: %u\n", ed->ehdr.e_shnum);
+		PRT("\te_shstrndx: %u\n", ed->ehdr.e_shstrndx);
+	}
+}
+
+/*
+ * Dump the ELF Program Header Table.
+ */
+static void
+elf_print_phdr(struct elfdump *ed)
+{
+	GElf_Phdr	 ph;
+	size_t		 phnum, i;
+	int		 header;
+
+	if (elf_getphnum(ed->elf, &phnum) == 0) {
+		warnx("elf_getphnum failed: %s", elf_errmsg(-1));
+		return;
+	}
+	header = 0;
+	for (i = 0; i < phnum; i++) {
+		if (gelf_getphdr(ed->elf, i, &ph) != &ph) {
+			warnx("elf_getphdr failed: %s", elf_errmsg(-1));
+			continue;
+		}
+		if (!STAILQ_EMPTY(&ed->snl) &&
+		    find_name(ed, elf_phdr_type_str(ph.p_type)) == NULL)
+			continue;
+		if (ed->flags & SOLARIS_FMT) {
+			PRT("\nProgram Header[%zu]:\n", i);
+			PRT("    p_vaddr:      %#-14jx", (uintmax_t)ph.p_vaddr);
+			PRT("  p_flags:    [ %s ]\n",
+			    p_flags[ph.p_flags & 0x7]);
+			PRT("    p_paddr:      %#-14jx", (uintmax_t)ph.p_paddr);
+			PRT("  p_type:     [ %s ]\n",
+			    elf_phdr_type_str(ph.p_type));
+			PRT("    p_filesz:     %#-14jx",
+			    (uintmax_t)ph.p_filesz);
+			PRT("  p_memsz:    %#jx\n", (uintmax_t)ph.p_memsz);
+			PRT("    p_offset:     %#-14jx",
+			    (uintmax_t)ph.p_offset);
+			PRT("  p_align:    %#jx\n", (uintmax_t)ph.p_align);
+		} else {
+			if (!header) {
+				PRT("\nprogram header:\n");
+				header = 1;
+			}
+			PRT("\n");
+			PRT("entry: %zu\n", i);
+			PRT("\tp_type: %s\n", elf_phdr_type_str(ph.p_type));
+			PRT("\tp_offset: %ju\n", (uintmax_t)ph.p_offset);
+			PRT("\tp_vaddr: %#jx\n", (uintmax_t)ph.p_vaddr);
+			PRT("\tp_paddr: %#jx\n", (uintmax_t)ph.p_paddr);
+			PRT("\tp_filesz: %ju\n", (uintmax_t)ph.p_filesz);
+			PRT("\tp_memsz: %ju\n", (uintmax_t)ph.p_memsz);
+			PRT("\tp_flags: %s\n", p_flags[ph.p_flags & 0x7]);
+			PRT("\tp_align: %ju\n", (uintmax_t)ph.p_align);
+		}
+	}
+}
+
+/*
+ * Dump the ELF Section Header Table.
+ */
+static void
+elf_print_shdr(struct elfdump *ed)
+{
+	struct section *s;
+	size_t i;
+
+	if (!STAILQ_EMPTY(&ed->snl))
+		return;
+
+	if ((ed->flags & SOLARIS_FMT) == 0)
+		PRT("\nsection header:\n");
+	for (i = 0; i < ed->shnum; i++) {
+		s = &ed->sl[i];
+		if (ed->flags & SOLARIS_FMT) {
+			if (i == 0)
+				continue;
+			PRT("\nSection Header[%zu]:", i);
+			PRT("  sh_name: %s\n", s->name);
+			PRT("    sh_addr:      %#-14jx", (uintmax_t)s->addr);
+			if (s->flags != 0)
+				PRT("  sh_flags:   [ %s ]\n", sh_flags(s->flags));
+			else
+				PRT("  sh_flags:   0\n");
+			PRT("    sh_size:      %#-14jx", (uintmax_t)s->sz);
+			PRT("  sh_type:    [ %s ]\n",
+			    sh_types(ed->ehdr.e_machine, s->type));
+			PRT("    sh_offset:    %#-14jx", (uintmax_t)s->off);
+			PRT("  sh_entsize: %#jx\n", (uintmax_t)s->entsize);
+			PRT("    sh_link:      %-14u", s->link);
+			PRT("  sh_info:    %u\n", s->info);
+			PRT("    sh_addralign: %#jx\n", (uintmax_t)s->align);
+		} else {
+			PRT("\n");
+			PRT("entry: %ju\n", (uintmax_t)i);
+			PRT("\tsh_name: %s\n", s->name);
+			PRT("\tsh_type: %s\n",
+			    sh_types(ed->ehdr.e_machine, s->type));
+			PRT("\tsh_flags: %s\n", sh_flags(s->flags));
+			PRT("\tsh_addr: %#jx\n", (uintmax_t)s->addr);
+			PRT("\tsh_offset: %ju\n", (uintmax_t)s->off);
+			PRT("\tsh_size: %ju\n", (uintmax_t)s->sz);
+			PRT("\tsh_link: %u\n", s->link);
+			PRT("\tsh_info: %u\n", s->info);
+			PRT("\tsh_addralign: %ju\n", (uintmax_t)s->align);
+			PRT("\tsh_entsize: %ju\n", (uintmax_t)s->entsize);
+		}
+	}
+}
+
+/*
+ * Return number of entries in the given section. We'd prefer ent_count be a
+ * size_t, but libelf APIs already use int for section indices.
+ */
+static int
+get_ent_count(const struct section *s, int *ent_count)
+{
+	if (s->entsize == 0) {
+		warnx("section %s has entry size 0", s->name);
+		return (0);
+	} else if (s->sz / s->entsize > INT_MAX) {
+		warnx("section %s has invalid section count", s->name);
+		return (0);
+	}
+	*ent_count = (int)(s->sz / s->entsize);
+	return (1);
+}
+
+/*
+ * Retrieve the content of the corresponding SHT_SUNW_versym section for
+ * a symbol table section.
+ */
+static void
+get_versym(struct elfdump *ed, int i, uint16_t **vs, int *nvs)
+{
+	struct section	*s;
+	Elf_Data	*data;
+	size_t		 j;
+	int		 elferr;
+
+	s = NULL;
+	for (j = 0; j < ed->shnum; j++) {
+		s = &ed->sl[j];
+		if (s->type == SHT_SUNW_versym && s->link == (uint32_t)i)
+			break;
+	}
+	if (j >= ed->shnum) {
+		*vs = NULL;
+		return;
+	}
+	(void) elf_errno();
+	if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_getdata failed: %s", elf_errmsg(elferr));
+		*vs = NULL;
+		return;
+	}
+
+	*vs = data->d_buf;
+	assert(data->d_size == s->sz);
+	if (!get_ent_count(s, nvs))
+		*nvs = 0;
+}
+
+/*
+ * Dump the symbol table section.
+ */
+static void
+elf_print_symtab(struct elfdump *ed, int i)
+{
+	struct section	*s;
+	const char	*name;
+	uint16_t	*vs;
+	char		 idx[13];
+	Elf_Data	*data;
+	GElf_Sym	 sym;
+	int		 len, j, elferr, nvs;
+
+	s = &ed->sl[i];
+	if (ed->flags & SOLARIS_FMT)
+		PRT("\nSymbol Table Section:  %s\n", s->name);
+	else
+		PRT("\nsymbol table (%s):\n", s->name);
+	(void) elf_errno();
+	if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_getdata failed: %s", elf_errmsg(elferr));
+		return;
+	}
+	vs = NULL;
+	nvs = 0;
+	assert(data->d_size == s->sz);
+	if (!get_ent_count(s, &len))
+		return;
+	if (ed->flags & SOLARIS_FMT) {
+		if (ed->ec == ELFCLASS32)
+			PRT("     index    value       ");
+		else
+			PRT("     index        value           ");
+		PRT("size     type bind oth ver shndx       name\n");
+		get_versym(ed, i, &vs, &nvs);
+		if (vs != NULL && nvs != len) {
+			warnx("#symbol not equal to #versym");
+			vs = NULL;
+		}
+	}
+	for (j = 0; j < len; j++) {
+		if (gelf_getsym(data, j, &sym) != &sym) {
+			warnx("gelf_getsym failed: %s", elf_errmsg(-1));
+			continue;
+		}
+		name = get_string(ed, s->link, sym.st_name);
+		if (ed->flags & SOLARIS_FMT) {
+			snprintf(idx, sizeof(idx), "[%d]", j);
+			if (ed->ec == ELFCLASS32)
+				PRT("%10s  ", idx);
+			else
+				PRT("%10s      ", idx);
+			PRT("0x%8.8jx ", (uintmax_t)sym.st_value);
+			if (ed->ec == ELFCLASS32)
+				PRT("0x%8.8jx  ", (uintmax_t)sym.st_size);
+			else
+				PRT("0x%12.12jx  ", (uintmax_t)sym.st_size);
+			PRT("%s ", st_type_S(GELF_ST_TYPE(sym.st_info)));
+			PRT("%s  ", st_bindings_S(GELF_ST_BIND(sym.st_info)));
+			PRT("%c  ", st_others[sym.st_other]);
+			PRT("%3u ", (vs == NULL ? 0 : vs[j]));
+			PRT("%-11.11s ", sh_name(ed, sym.st_shndx));
+			PRT("%s\n", name);
+		} else {
+			PRT("\nentry: %d\n", j);
+			PRT("\tst_name: %s\n", name);
+			PRT("\tst_value: %#jx\n", (uintmax_t)sym.st_value);
+			PRT("\tst_size: %ju\n", (uintmax_t)sym.st_size);
+			PRT("\tst_info: %s %s\n",
+			    st_type(ed->ehdr.e_machine,
+			    GELF_ST_TYPE(sym.st_info)),
+			    st_bindings(GELF_ST_BIND(sym.st_info)));
+			PRT("\tst_shndx: %ju\n", (uintmax_t)sym.st_shndx);
+		}
+	}
+}
+
+/*
+ * Dump the symbol tables. (.dynsym and .symtab)
+ */
+static void
+elf_print_symtabs(struct elfdump *ed)
+{
+	size_t i;
+
+	for (i = 0; i < ed->shnum; i++)
+		if ((ed->sl[i].type == SHT_SYMTAB ||
+		    ed->sl[i].type == SHT_DYNSYM) &&
+		    (STAILQ_EMPTY(&ed->snl) || find_name(ed, ed->sl[i].name)))
+			elf_print_symtab(ed, i);
+}
+
+/*
+ * Dump the content of .dynamic section.
+ */
+static void
+elf_print_dynamic(struct elfdump *ed)
+{
+	struct section	*s;
+	const char	*name;
+	char		 idx[13];
+	Elf_Data	*data;
+	GElf_Dyn	 dyn;
+	int		 elferr, i, len;
+
+	s = NULL;
+	for (i = 0; (size_t)i < ed->shnum; i++) {
+		s = &ed->sl[i];
+		if (s->type == SHT_DYNAMIC &&
+		    (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name)))
+			break;
+	}
+	if ((size_t)i >= ed->shnum)
+		return;
+
+	if (ed->flags & SOLARIS_FMT) {
+		PRT("Dynamic Section:  %s\n", s->name);
+		PRT("     index  tag               value\n");
+	} else
+		PRT("\ndynamic:\n");
+	(void) elf_errno();
+	if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_getdata failed: %s", elf_errmsg(elferr));
+		return;
+	}
+	assert(data->d_size == s->sz);
+	if (!get_ent_count(s, &len))
+		return;
+	for (i = 0; i < len; i++) {
+		if (gelf_getdyn(data, i, &dyn) != &dyn) {
+			warnx("gelf_getdyn failed: %s", elf_errmsg(-1));
+			continue;
+		}
+
+		if (ed->flags & SOLARIS_FMT) {
+			snprintf(idx, sizeof(idx), "[%d]", i);
+			PRT("%10s  %-16s ", idx, d_tags(dyn.d_tag));
+		} else {
+			PRT("\n");
+			PRT("entry: %d\n", i);
+			PRT("\td_tag: %s\n", d_tags(dyn.d_tag));
+		}
+		switch(dyn.d_tag) {
+		case DT_NEEDED:
+		case DT_SONAME:
+		case DT_RPATH:
+		case DT_RUNPATH:
+			if ((name = elf_strptr(ed->elf, s->link,
+				    dyn.d_un.d_val)) == NULL)
+				name = "";
+			if (ed->flags & SOLARIS_FMT)
+				PRT("%#-16jx %s\n", (uintmax_t)dyn.d_un.d_val,
+				    name);
+			else
+				PRT("\td_val: %s\n", name);
+			break;
+		case DT_PLTRELSZ:
+		case DT_RELA:
+		case DT_RELASZ:
+		case DT_RELAENT:
+		case DT_RELACOUNT:
+		case DT_STRSZ:
+		case DT_SYMENT:
+		case DT_RELSZ:
+		case DT_RELENT:
+		case DT_PLTREL:
+		case DT_VERDEF:
+		case DT_VERDEFNUM:
+		case DT_VERNEED:
+		case DT_VERNEEDNUM:
+		case DT_VERSYM:
+			if (ed->flags & SOLARIS_FMT)
+				PRT("%#jx\n", (uintmax_t)dyn.d_un.d_val);
+			else
+				PRT("\td_val: %ju\n",
+				    (uintmax_t)dyn.d_un.d_val);
+			break;
+		case DT_PLTGOT:
+		case DT_HASH:
+		case DT_GNU_HASH:
+		case DT_STRTAB:
+		case DT_SYMTAB:
+		case DT_INIT:
+		case DT_FINI:
+		case DT_REL:
+		case DT_JMPREL:
+		case DT_DEBUG:
+			if (ed->flags & SOLARIS_FMT)
+				PRT("%#jx\n", (uintmax_t)dyn.d_un.d_ptr);
+			else
+				PRT("\td_ptr: %#jx\n",
+				    (uintmax_t)dyn.d_un.d_ptr);
+			break;
+		case DT_NULL:
+		case DT_SYMBOLIC:
+		case DT_TEXTREL:
+		default:
+			if (ed->flags & SOLARIS_FMT)
+				PRT("\n");
+			break;
+		}
+	}
+}
+
+/*
+ * Dump a .rel/.rela section entry.
+ */
+static void
+elf_print_rel_entry(struct elfdump *ed, struct section *s, int j,
+    struct rel_entry *r)
+{
+
+	if (ed->flags & SOLARIS_FMT) {
+		PRT("        %-23s ", elftc_reloc_type_str(ed->ehdr.e_machine,
+			GELF_R_TYPE(r->u_r.rel.r_info)));
+		PRT("%#12jx ", (uintmax_t)r->u_r.rel.r_offset);
+		if (r->type == SHT_RELA)
+			PRT("%10jd  ", (intmax_t)r->u_r.rela.r_addend);
+		else
+			PRT("    ");
+		PRT("%-14s ", s->name);
+		PRT("%s\n", r->symn);
+	} else {
+		PRT("\n");
+		PRT("entry: %d\n", j);
+		PRT("\tr_offset: %#jx\n", (uintmax_t)r->u_r.rel.r_offset);
+		if (ed->ec == ELFCLASS32)
+			PRT("\tr_info: %#jx\n", (uintmax_t)
+			    ELF32_R_INFO(ELF64_R_SYM(r->u_r.rel.r_info),
+			    ELF64_R_TYPE(r->u_r.rel.r_info)));
+		else
+			PRT("\tr_info: %#jx\n", (uintmax_t)r->u_r.rel.r_info);
+		if (r->type == SHT_RELA)
+			PRT("\tr_addend: %jd\n",
+			    (intmax_t)r->u_r.rela.r_addend);
+	}
+}
+
+/*
+ * Dump a relocation section of type SHT_RELA.
+ */
+static void
+elf_print_rela(struct elfdump *ed, struct section *s, Elf_Data *data)
+{
+	struct rel_entry	r;
+	int			j, len;
+
+	if (ed->flags & SOLARIS_FMT) {
+		PRT("\nRelocation Section:  %s\n", s->name);
+		PRT("        type                          offset     "
+		    "addend  section        with respect to\n");
+	} else
+		PRT("\nrelocation with addend (%s):\n", s->name);
+	r.type = SHT_RELA;
+	assert(data->d_size == s->sz);
+	if (!get_ent_count(s, &len))
+		return;
+	for (j = 0; j < len; j++) {
+		if (gelf_getrela(data, j, &r.u_r.rela) != &r.u_r.rela) {
+			warnx("gelf_getrela failed: %s",
+			    elf_errmsg(-1));
+			continue;
+		}
+		r.symn = get_symbol_name(ed, s->link,
+		    GELF_R_SYM(r.u_r.rela.r_info));
+		elf_print_rel_entry(ed, s, j, &r);
+	}
+}
+
+/*
+ * Dump a relocation section of type SHT_REL.
+ */
+static void
+elf_print_rel(struct elfdump *ed, struct section *s, Elf_Data *data)
+{
+	struct rel_entry	r;
+	int			j, len;
+
+	if (ed->flags & SOLARIS_FMT) {
+		PRT("\nRelocation Section:  %s\n", s->name);
+		PRT("        type                          offset     "
+		    "section        with respect to\n");
+	} else
+		PRT("\nrelocation (%s):\n", s->name);
+	r.type = SHT_REL;
+	assert(data->d_size == s->sz);
+	if (!get_ent_count(s, &len))
+		return;
+	for (j = 0; j < len; j++) {
+		if (gelf_getrel(data, j, &r.u_r.rel) != &r.u_r.rel) {
+			warnx("gelf_getrel failed: %s", elf_errmsg(-1));
+			continue;
+		}
+		r.symn = get_symbol_name(ed, s->link,
+		    GELF_R_SYM(r.u_r.rel.r_info));
+		elf_print_rel_entry(ed, s, j, &r);
+	}
+}
+
+/*
+ * Dump relocation sections.
+ */
+static void
+elf_print_reloc(struct elfdump *ed)
+{
+	struct section	*s;
+	Elf_Data	*data;
+	size_t		 i;
+	int		 elferr;
+
+	for (i = 0; i < ed->shnum; i++) {
+		s = &ed->sl[i];
+		if ((s->type == SHT_REL || s->type == SHT_RELA) &&
+		    (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) {
+			(void) elf_errno();
+			if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+				elferr = elf_errno();
+				if (elferr != 0)
+					warnx("elf_getdata failed: %s",
+					    elf_errmsg(elferr));
+				continue;
+			}
+			if (s->type == SHT_REL)
+				elf_print_rel(ed, s, data);
+			else
+				elf_print_rela(ed, s, data);
+		}
+	}
+}
+
+/*
+ * Dump the content of PT_INTERP segment.
+ */
+static void
+elf_print_interp(struct elfdump *ed)
+{
+	const char *s;
+	GElf_Phdr phdr;
+	size_t filesize, i, phnum;
+
+	if (!STAILQ_EMPTY(&ed->snl) && find_name(ed, "PT_INTERP") == NULL)
+		return;
+
+	if ((s = elf_rawfile(ed->elf, &filesize)) == NULL) {
+		warnx("elf_rawfile failed: %s", elf_errmsg(-1));
+		return;
+	}
+	if (!elf_getphnum(ed->elf, &phnum)) {
+		warnx("elf_getphnum failed: %s", elf_errmsg(-1));
+		return;
+	}
+	for (i = 0; i < phnum; i++) {
+		if (gelf_getphdr(ed->elf, i, &phdr) != &phdr) {
+			warnx("elf_getphdr failed: %s", elf_errmsg(-1));
+			continue;
+		}
+		if (phdr.p_type == PT_INTERP) {
+			if (phdr.p_offset >= filesize) {
+				warnx("invalid phdr offset");
+				continue;
+			}
+			PRT("\ninterp:\n");
+			PRT("\t%s\n", s + phdr.p_offset);
+		}
+	}
+}
+
+/*
+ * Search the relocation sections for entries referring to the .got section.
+ */
+static void
+find_gotrel(struct elfdump *ed, struct section *gs, struct rel_entry *got)
+{
+	struct section		*s;
+	struct rel_entry	 r;
+	Elf_Data		*data;
+	size_t			 i;
+	int			 elferr, j, k, len;
+
+	for(i = 0; i < ed->shnum; i++) {
+		s = &ed->sl[i];
+		if (s->type != SHT_REL && s->type != SHT_RELA)
+			continue;
+		(void) elf_errno();
+		if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+			elferr = elf_errno();
+			if (elferr != 0)
+				warnx("elf_getdata failed: %s",
+				    elf_errmsg(elferr));
+			return;
+		}
+		memset(&r, 0, sizeof(struct rel_entry));
+		r.type = s->type;
+		assert(data->d_size == s->sz);
+		if (!get_ent_count(s, &len))
+			return;
+		for (j = 0; j < len; j++) {
+			if (s->type == SHT_REL) {
+				if (gelf_getrel(data, j, &r.u_r.rel) !=
+				    &r.u_r.rel) {
+					warnx("gelf_getrel failed: %s",
+					    elf_errmsg(-1));
+					continue;
+				}
+			} else {
+				if (gelf_getrela(data, j, &r.u_r.rela) !=
+				    &r.u_r.rela) {
+					warnx("gelf_getrel failed: %s",
+					    elf_errmsg(-1));
+					continue;
+				}
+			}
+			if (r.u_r.rel.r_offset >= gs->addr &&
+			    r.u_r.rel.r_offset < gs->addr + gs->sz) {
+				r.symn = get_symbol_name(ed, s->link,
+				    GELF_R_SYM(r.u_r.rel.r_info));
+				k = (r.u_r.rel.r_offset - gs->addr) /
+				    gs->entsize;
+				memcpy(&got[k], &r, sizeof(struct rel_entry));
+			}
+		}
+	}
+}
+
+static void
+elf_print_got_section(struct elfdump *ed, struct section *s)
+{
+	struct rel_entry	*got;
+	Elf_Data		*data, dst;
+	int			 elferr, i, len;
+
+	if (s->entsize == 0) {
+		/* XXX IA64 GOT section generated by gcc has entry size 0. */
+		if (s->align != 0)
+			s->entsize = s->align;
+		else
+			return;
+	}
+
+	if (!get_ent_count(s, &len))
+		return;
+	if (ed->flags & SOLARIS_FMT)
+		PRT("\nGlobal Offset Table Section:  %s  (%d entries)\n",
+		    s->name, len);
+	else
+		PRT("\nglobal offset table: %s\n", s->name);
+	(void) elf_errno();
+	if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_getdata failed: %s", elf_errmsg(elferr));
+		return;
+	}
+
+	/*
+	 * GOT section has section type SHT_PROGBITS, thus libelf treats it as
+	 * byte stream and will not perform any translation on it. As a result,
+	 * an exlicit call to gelf_xlatetom is needed here. Depends on arch,
+	 * GOT section should be translated to either WORD or XWORD.
+	 */
+	if (ed->ec == ELFCLASS32)
+		data->d_type = ELF_T_WORD;
+	else
+		data->d_type = ELF_T_XWORD;
+	memcpy(&dst, data, sizeof(Elf_Data));
+	if (gelf_xlatetom(ed->elf, &dst, data, ed->ehdr.e_ident[EI_DATA]) !=
+	    &dst) {
+		warnx("gelf_xlatetom failed: %s", elf_errmsg(-1));
+		return;
+	}
+	assert(dst.d_size == s->sz);
+	if (ed->flags & SOLARIS_FMT) {
+		/*
+		 * In verbose/Solaris mode, we search the relocation sections
+		 * and try to find the corresponding reloc entry for each GOT
+		 * section entry.
+		 */
+		if ((got = calloc(len, sizeof(struct rel_entry))) == NULL)
+			err(EXIT_FAILURE, "calloc failed");
+		find_gotrel(ed, s, got);
+		if (ed->ec == ELFCLASS32) {
+			PRT(" ndx     addr      value    reloc              ");
+			PRT("addend   symbol\n");
+		} else {
+			PRT(" ndx     addr              value             ");
+			PRT("reloc              addend       symbol\n");
+		}
+		for(i = 0; i < len; i++) {
+			PRT("[%5.5d]  ", i);
+			if (ed->ec == ELFCLASS32) {
+				PRT("%-8.8jx  ",
+				    (uintmax_t) (s->addr + i * s->entsize));
+				PRT("%-8.8x ", *((uint32_t *)dst.d_buf + i));
+			} else {
+				PRT("%-16.16jx  ",
+				    (uintmax_t) (s->addr + i * s->entsize));
+				PRT("%-16.16jx  ",
+				    (uintmax_t) *((uint64_t *)dst.d_buf + i));
+			}
+			PRT("%-18s ", elftc_reloc_type_str(ed->ehdr.e_machine,
+				GELF_R_TYPE(got[i].u_r.rel.r_info)));
+			if (ed->ec == ELFCLASS32)
+				PRT("%-8.8jd ",
+				    (intmax_t)got[i].u_r.rela.r_addend);
+			else
+				PRT("%-12.12jd ",
+				    (intmax_t)got[i].u_r.rela.r_addend);
+			if (got[i].symn == NULL)
+				got[i].symn = "";
+			PRT("%s\n", got[i].symn);
+		}
+		free(got);
+	} else {
+		for(i = 0; i < len; i++) {
+			PRT("\nentry: %d\n", i);
+			if (ed->ec == ELFCLASS32)
+				PRT("\t%#x\n", *((uint32_t *)dst.d_buf + i));
+			else
+				PRT("\t%#jx\n",
+				    (uintmax_t) *((uint64_t *)dst.d_buf + i));
+		}
+	}
+}
+
+/*
+ * Dump the content of Global Offset Table section.
+ */
+static void
+elf_print_got(struct elfdump *ed)
+{
+	struct section	*s;
+	size_t		 i;
+
+	if (!STAILQ_EMPTY(&ed->snl))
+		return;
+
+	s = NULL;
+	for (i = 0; i < ed->shnum; i++) {
+		s = &ed->sl[i];
+		if (s->name && !strncmp(s->name, ".got", 4) &&
+		    (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name)))
+			elf_print_got_section(ed, s);
+	}
+}
+
+/*
+ * Dump the content of .note.ABI-tag section.
+ */
+static void
+elf_print_note(struct elfdump *ed)
+{
+	struct section	*s;
+	Elf_Data        *data;
+	Elf_Note	*en;
+	uint32_t	 namesz;
+	uint32_t	 descsz;
+	uint32_t	 desc;
+	size_t		 count;
+	int		 elferr, i;
+	uint8_t		*src;
+	char		 idx[17];
+
+	s = NULL;
+	for (i = 0; (size_t)i < ed->shnum; i++) {
+		s = &ed->sl[i];
+		if (s->type == SHT_NOTE && s->name &&
+		    !strcmp(s->name, ".note.ABI-tag") &&
+		    (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name)))
+			break;
+	}
+	if ((size_t)i >= ed->shnum)
+		return;
+	if (ed->flags & SOLARIS_FMT)
+		PRT("\nNote Section:  %s\n", s->name);
+	else
+		PRT("\nnote (%s):\n", s->name);
+	(void) elf_errno();
+	if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_getdata failed: %s", elf_errmsg(elferr));
+		return;
+	}
+	src = data->d_buf;
+	count = data->d_size;
+	while (count > sizeof(Elf_Note)) {
+		en = (Elf_Note *) (uintptr_t) src;
+		namesz = en->n_namesz;
+		descsz = en->n_descsz;
+		src += sizeof(Elf_Note);
+		count -= sizeof(Elf_Note);
+		if (roundup2(namesz, 4) + roundup2(descsz, 4) > count) {
+			warnx("truncated note section");
+			return;
+		}
+		if (ed->flags & SOLARIS_FMT) {
+			PRT("\n    type   %#x\n", en->n_type);
+			PRT("    namesz %#x:\n", en->n_namesz);
+			PRT("%s\n", src);
+		} else
+			PRT("\t%s ", src);
+		src += roundup2(namesz, 4);
+		count -= roundup2(namesz, 4);
+
+		/*
+		 * Note that we dump the whole desc part if we're in
+		 * "Solaris mode", while in the normal mode, we only look
+		 * at the first 4 bytes (a 32bit word) of the desc, i.e,
+		 * we assume that it's always a FreeBSD version number.
+		 */
+		if (ed->flags & SOLARIS_FMT) {
+			PRT("    descsz %#x:", en->n_descsz);
+			for (i = 0; (uint32_t)i < descsz; i++) {
+				if ((i & 0xF) == 0) {
+					snprintf(idx, sizeof(idx), "desc[%d]",
+					    i);
+					PRT("\n      %-9s", idx);
+				} else if ((i & 0x3) == 0)
+					PRT("  ");
+				PRT(" %2.2x", src[i]);
+			}
+			PRT("\n");
+		} else {
+			if (ed->ehdr.e_ident[EI_DATA] == ELFDATA2MSB)
+				desc = be32dec(src);
+			else
+				desc = le32dec(src);
+			PRT("%d\n", desc);
+		}
+		src += roundup2(descsz, 4);
+		count -= roundup2(descsz, 4);
+	}
+}
+
+/*
+ * Dump a hash table.
+ */
+static void
+elf_print_svr4_hash(struct elfdump *ed, struct section *s)
+{
+	Elf_Data	*data;
+	uint32_t	*buf;
+	uint32_t	*bucket, *chain;
+	uint32_t	 nbucket, nchain;
+	uint32_t	*bl, *c, maxl, total;
+	uint32_t	 i, j;
+	int		 first, elferr;
+	char		 idx[10];
+
+	if (ed->flags & SOLARIS_FMT)
+		PRT("\nHash Section:  %s\n", s->name);
+	else
+		PRT("\nhash table (%s):\n", s->name);
+	(void) elf_errno();
+	if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_getdata failed: %s",
+			    elf_errmsg(elferr));
+		return;
+	}
+	if (data->d_size < 2 * sizeof(uint32_t)) {
+		warnx(".hash section too small");
+		return;
+	}
+	buf = data->d_buf;
+	nbucket = buf[0];
+	nchain = buf[1];
+	if (nbucket <= 0 || nchain <= 0) {
+		warnx("Malformed .hash section");
+		return;
+	}
+	if (data->d_size !=
+	    ((uint64_t)nbucket + (uint64_t)nchain + 2) * sizeof(uint32_t)) {
+		warnx("Malformed .hash section");
+		return;
+	}
+	bucket = &buf[2];
+	chain = &buf[2 + nbucket];
+
+	if (ed->flags & SOLARIS_FMT) {
+		maxl = 0;
+		if ((bl = calloc(nbucket, sizeof(*bl))) == NULL)
+			err(EXIT_FAILURE, "calloc failed");
+		for (i = 0; i < nbucket; i++)
+			for (j = bucket[i]; j > 0 && j < nchain; j = chain[j])
+				if (++bl[i] > maxl)
+					maxl = bl[i];
+		if ((c = calloc(maxl + 1, sizeof(*c))) == NULL)
+			err(EXIT_FAILURE, "calloc failed");
+		for (i = 0; i < nbucket; i++)
+			c[bl[i]]++;
+		PRT("    bucket    symndx    name\n");
+		for (i = 0; i < nbucket; i++) {
+			first = 1;
+			for (j = bucket[i]; j > 0 && j < nchain; j = chain[j]) {
+				if (first) {
+					PRT("%10d  ", i);
+					first = 0;
+				} else
+					PRT("            ");
+				snprintf(idx, sizeof(idx), "[%d]", j);
+				PRT("%-10s  ", idx);
+				PRT("%s\n", get_symbol_name(ed, s->link, j));
+			}
+		}
+		PRT("\n");
+		total = 0;
+		for (i = 0; i <= maxl; i++) {
+			total += c[i] * i;
+			PRT("%10u  buckets contain %8d symbols\n", c[i], i);
+		}
+		PRT("%10u  buckets         %8u symbols (globals)\n", nbucket,
+		    total);
+	} else {
+		PRT("\nnbucket: %u\n", nbucket);
+		PRT("nchain: %u\n\n", nchain);
+		for (i = 0; i < nbucket; i++)
+			PRT("bucket[%d]:\n\t%u\n\n", i, bucket[i]);
+		for (i = 0; i < nchain; i++)
+			PRT("chain[%d]:\n\t%u\n\n", i, chain[i]);
+	}
+}
+
+/*
+ * Dump a 64bit hash table.
+ */
+static void
+elf_print_svr4_hash64(struct elfdump *ed, struct section *s)
+{
+	Elf_Data	*data, dst;
+	uint64_t	*buf;
+	uint64_t	*bucket, *chain;
+	uint64_t	 nbucket, nchain;
+	uint64_t	*bl, *c, j, maxl, total;
+	size_t		 i;
+	int		 elferr, first;
+	char		 idx[10];
+
+	if (ed->flags & SOLARIS_FMT)
+		PRT("\nHash Section:  %s\n", s->name);
+	else
+		PRT("\nhash table (%s):\n", s->name);
+
+	/*
+	 * ALPHA uses 64-bit hash entries. Since libelf assumes that
+	 * .hash section contains only 32-bit entry, an explicit
+	 * gelf_xlatetom is needed here.
+	 */
+	(void) elf_errno();
+	if ((data = elf_rawdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_rawdata failed: %s",
+			    elf_errmsg(elferr));
+		return;
+	}
+	data->d_type = ELF_T_XWORD;
+	memcpy(&dst, data, sizeof(Elf_Data));
+	if (gelf_xlatetom(ed->elf, &dst, data,
+		ed->ehdr.e_ident[EI_DATA]) != &dst) {
+		warnx("gelf_xlatetom failed: %s", elf_errmsg(-1));
+		return;
+	}
+	if (dst.d_size < 2 * sizeof(uint64_t)) {
+		warnx(".hash section too small");
+		return;
+	}
+	buf = dst.d_buf;
+	nbucket = buf[0];
+	nchain = buf[1];
+	if (nbucket <= 0 || nchain <= 0) {
+		warnx("Malformed .hash section");
+		return;
+	}
+	if (dst.d_size != (nbucket + nchain + 2) * sizeof(uint64_t)) {
+		warnx("Malformed .hash section");
+		return;
+	}
+	bucket = &buf[2];
+	chain = &buf[2 + nbucket];
+
+	if (ed->flags & SOLARIS_FMT) {
+		maxl = 0;
+		if ((bl = calloc(nbucket, sizeof(*bl))) == NULL)
+			err(EXIT_FAILURE, "calloc failed");
+		for (i = 0; i < nbucket; i++)
+			for (j = bucket[i]; j > 0 && j < nchain; j = chain[j])
+				if (++bl[i] > maxl)
+					maxl = bl[i];
+		if ((c = calloc(maxl + 1, sizeof(*c))) == NULL)
+			err(EXIT_FAILURE, "calloc failed");
+		for (i = 0; i < nbucket; i++)
+			c[bl[i]]++;
+		PRT("    bucket    symndx    name\n");
+		for (i = 0; i < nbucket; i++) {
+			first = 1;
+			for (j = bucket[i]; j > 0 && j < nchain; j = chain[j]) {
+				if (first) {
+					PRT("%10zu  ", i);
+					first = 0;
+				} else
+					PRT("            ");
+				snprintf(idx, sizeof(idx), "[%zu]", (size_t)j);
+				PRT("%-10s  ", idx);
+				PRT("%s\n", get_symbol_name(ed, s->link, j));
+			}
+		}
+		PRT("\n");
+		total = 0;
+		for (i = 0; i <= maxl; i++) {
+			total += c[i] * i;
+			PRT("%10ju  buckets contain %8zu symbols\n",
+			    (uintmax_t)c[i], i);
+		}
+		PRT("%10ju  buckets         %8ju symbols (globals)\n",
+		    (uintmax_t)nbucket, (uintmax_t)total);
+	} else {
+		PRT("\nnbucket: %ju\n", (uintmax_t)nbucket);
+		PRT("nchain: %ju\n\n", (uintmax_t)nchain);
+		for (i = 0; i < nbucket; i++)
+			PRT("bucket[%zu]:\n\t%ju\n\n", i, (uintmax_t)bucket[i]);
+		for (i = 0; i < nchain; i++)
+			PRT("chain[%zu]:\n\t%ju\n\n", i, (uintmax_t)chain[i]);
+	}
+
+}
+
+/*
+ * Dump a GNU hash table.
+ */
+static void
+elf_print_gnu_hash(struct elfdump *ed, struct section *s)
+{
+	struct section	*ds;
+	Elf_Data	*data;
+	uint32_t	*buf;
+	uint32_t	*bucket, *chain;
+	uint32_t	 nbucket, nchain, symndx, maskwords, shift2;
+	uint32_t	*bl, *c, maxl, total;
+	uint32_t	 i, j;
+	int		 first, elferr, dynsymcount;
+	char		 idx[10];
+
+	if (ed->flags & SOLARIS_FMT)
+		PRT("\nGNU Hash Section:  %s\n", s->name);
+	else
+		PRT("\ngnu hash table (%s):\n", s->name);
+	(void) elf_errno();
+	if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_getdata failed: %s",
+			    elf_errmsg(elferr));
+		return;
+	}
+	if (data->d_size < 4 * sizeof(uint32_t)) {
+		warnx(".gnu.hash section too small");
+		return;
+	}
+	buf = data->d_buf;
+	nbucket = buf[0];
+	symndx = buf[1];
+	maskwords = buf[2];
+	shift2 = buf[3];
+	buf += 4;
+	if (s->link >= ed->shnum) {
+		warnx("Malformed .gnu.hash section");
+		return;
+	}
+	ds = &ed->sl[s->link];
+	if (!get_ent_count(ds, &dynsymcount))
+		return;
+	if (symndx >= (uint32_t)dynsymcount) {
+		warnx("Malformed .gnu.hash section");
+		return;
+	}
+	nchain = dynsymcount - symndx;
+	if (data->d_size != 4 * sizeof(uint32_t) + maskwords *
+	    (ed->ec == ELFCLASS32 ? sizeof(uint32_t) : sizeof(uint64_t)) +
+	    ((uint64_t)nbucket + (uint64_t)nchain) * sizeof(uint32_t)) {
+		warnx("Malformed .gnu.hash section");
+		return;
+	}
+	bucket = buf + (ed->ec == ELFCLASS32 ? maskwords : maskwords * 2);
+	chain = bucket + nbucket;
+
+	if (ed->flags & SOLARIS_FMT) {
+		maxl = 0;
+		if ((bl = calloc(nbucket, sizeof(*bl))) == NULL)
+			err(EXIT_FAILURE, "calloc failed");
+		for (i = 0; i < nbucket; i++)
+			for (j = bucket[i]; j > 0 && j - symndx < nchain; j++) {
+				if (++bl[i] > maxl)
+					maxl = bl[i];
+				if (chain[j - symndx] & 1)
+					break;
+			}
+		if ((c = calloc(maxl + 1, sizeof(*c))) == NULL)
+			err(EXIT_FAILURE, "calloc failed");
+		for (i = 0; i < nbucket; i++)
+			c[bl[i]]++;
+		PRT("    bucket    symndx    name\n");
+		for (i = 0; i < nbucket; i++) {
+			first = 1;
+			for (j = bucket[i]; j > 0 && j - symndx < nchain; j++) {
+				if (first) {
+					PRT("%10d  ", i);
+					first = 0;
+				} else
+					PRT("            ");
+				snprintf(idx, sizeof(idx), "[%d]", j );
+				PRT("%-10s  ", idx);
+				PRT("%s\n", get_symbol_name(ed, s->link, j));
+				if (chain[j - symndx] & 1)
+					break;
+			}
+		}
+		PRT("\n");
+		total = 0;
+		for (i = 0; i <= maxl; i++) {
+			total += c[i] * i;
+			PRT("%10u  buckets contain %8d symbols\n", c[i], i);
+		}
+		PRT("%10u  buckets         %8u symbols (globals)\n", nbucket,
+		    total);
+	} else {
+		PRT("\nnbucket: %u\n", nbucket);
+		PRT("symndx: %u\n", symndx);
+		PRT("maskwords: %u\n", maskwords);
+		PRT("shift2: %u\n", shift2);
+		PRT("nchain: %u\n\n", nchain);
+		for (i = 0; i < nbucket; i++)
+			PRT("bucket[%d]:\n\t%u\n\n", i, bucket[i]);
+		for (i = 0; i < nchain; i++)
+			PRT("chain[%d]:\n\t%u\n\n", i, chain[i]);
+	}
+}
+
+/*
+ * Dump hash tables.
+ */
+static void
+elf_print_hash(struct elfdump *ed)
+{
+	struct section	*s;
+	size_t		 i;
+
+	for (i = 0; i < ed->shnum; i++) {
+		s = &ed->sl[i];
+		if ((s->type == SHT_HASH || s->type == SHT_GNU_HASH) &&
+		    (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) {
+			if (s->type == SHT_GNU_HASH)
+				elf_print_gnu_hash(ed, s);
+			else if (ed->ehdr.e_machine == EM_ALPHA &&
+			    s->entsize == 8)
+				elf_print_svr4_hash64(ed, s);
+			else
+				elf_print_svr4_hash(ed, s);
+		}
+	}
+}
+
+/*
+ * Dump the content of a Version Definition(SHT_SUNW_Verdef) Section.
+ */
+static void
+elf_print_verdef(struct elfdump *ed, struct section *s)
+{
+	Elf_Data	*data;
+	Elf32_Verdef	*vd;
+	Elf32_Verdaux	*vda;
+	const char 	*str;
+	char		 idx[10];
+	uint8_t		*buf, *end, *buf2;
+	int		 i, j, elferr, count;
+
+	if (ed->flags & SOLARIS_FMT)
+		PRT("Version Definition Section:  %s\n", s->name);
+	else
+		PRT("\nversion definition section (%s):\n", s->name);
+	(void) elf_errno();
+	if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_getdata failed: %s",
+			    elf_errmsg(elferr));
+		return;
+	}
+	buf = data->d_buf;
+	end = buf + data->d_size;
+	i = 0;
+	if (ed->flags & SOLARIS_FMT)
+		PRT("     index  version                     dependency\n");
+	while (buf + sizeof(Elf32_Verdef) <= end) {
+		vd = (Elf32_Verdef *) (uintptr_t) buf;
+		if (ed->flags & SOLARIS_FMT) {
+			snprintf(idx, sizeof(idx), "[%d]", vd->vd_ndx);
+			PRT("%10s  ", idx);
+		} else {
+			PRT("\nentry: %d\n", i++);
+			PRT("\tvd_version: %u\n", vd->vd_version);
+			PRT("\tvd_flags: %u\n", vd->vd_flags);
+			PRT("\tvd_ndx: %u\n", vd->vd_ndx);
+			PRT("\tvd_cnt: %u\n", vd->vd_cnt);
+			PRT("\tvd_hash: %u\n", vd->vd_hash);
+			PRT("\tvd_aux: %u\n", vd->vd_aux);
+			PRT("\tvd_next: %u\n\n", vd->vd_next);
+		}
+		buf2 = buf + vd->vd_aux;
+		j = 0;
+		count = 0;
+		while (buf2 + sizeof(Elf32_Verdaux) <= end && j < vd->vd_cnt) {
+			vda = (Elf32_Verdaux *) (uintptr_t) buf2;
+			str = get_string(ed, s->link, vda->vda_name);
+			if (ed->flags & SOLARIS_FMT) {
+				if (count == 0)
+					PRT("%-26.26s", str);
+				else if (count == 1)
+					PRT("  %-20.20s", str);
+				else {
+					PRT("\n%40.40s", "");
+					PRT("%s", str);
+				}
+			} else {
+				PRT("\t\tvda: %d\n", j++);
+				PRT("\t\t\tvda_name: %s\n", str);
+				PRT("\t\t\tvda_next: %u\n", vda->vda_next);
+			}
+			if (vda->vda_next == 0) {
+				if (ed->flags & SOLARIS_FMT) {
+					if (vd->vd_flags & VER_FLG_BASE) {
+						if (count == 0)
+							PRT("%-20.20s", "");
+						PRT("%s", "[ BASE ]");
+					}
+					PRT("\n");
+				}
+				break;
+			}
+			if (ed->flags & SOLARIS_FMT)
+				count++;
+			buf2 += vda->vda_next;
+		}
+		if (vd->vd_next == 0)
+			break;
+		buf += vd->vd_next;
+	}
+}
+
+/*
+ * Dump the content of a Version Needed(SHT_SUNW_Verneed) Section.
+ */
+static void
+elf_print_verneed(struct elfdump *ed, struct section *s)
+{
+	Elf_Data	*data;
+	Elf32_Verneed	*vn;
+	Elf32_Vernaux	*vna;
+	uint8_t		*buf, *end, *buf2;
+	int		 i, j, elferr, first;
+
+	if (ed->flags & SOLARIS_FMT)
+		PRT("\nVersion Needed Section:  %s\n", s->name);
+	else
+		PRT("\nversion need section (%s):\n", s->name);
+	(void) elf_errno();
+	if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_getdata failed: %s",
+			    elf_errmsg(elferr));
+		return;
+	}
+	buf = data->d_buf;
+	end = buf + data->d_size;
+	if (ed->flags & SOLARIS_FMT)
+		PRT("            file                        version\n");
+	i = 0;
+	while (buf + sizeof(Elf32_Verneed) <= end) {
+		vn = (Elf32_Verneed *) (uintptr_t) buf;
+		if (ed->flags & SOLARIS_FMT)
+			PRT("            %-26.26s  ",
+			    get_string(ed, s->link, vn->vn_file));
+		else {
+			PRT("\nentry: %d\n", i++);
+			PRT("\tvn_version: %u\n", vn->vn_version);
+			PRT("\tvn_cnt: %u\n", vn->vn_cnt);
+			PRT("\tvn_file: %s\n",
+			    get_string(ed, s->link, vn->vn_file));
+			PRT("\tvn_aux: %u\n", vn->vn_aux);
+			PRT("\tvn_next: %u\n\n", vn->vn_next);
+		}
+		buf2 = buf + vn->vn_aux;
+		j = 0;
+		first = 1;
+		while (buf2 + sizeof(Elf32_Vernaux) <= end && j < vn->vn_cnt) {
+			vna = (Elf32_Vernaux *) (uintptr_t) buf2;
+			if (ed->flags & SOLARIS_FMT) {
+				if (!first)
+					PRT("%40.40s", "");
+				else
+					first = 0;
+				PRT("%s\n", get_string(ed, s->link,
+				    vna->vna_name));
+			} else {
+				PRT("\t\tvna: %d\n", j++);
+				PRT("\t\t\tvna_hash: %u\n", vna->vna_hash);
+				PRT("\t\t\tvna_flags: %u\n", vna->vna_flags);
+				PRT("\t\t\tvna_other: %u\n", vna->vna_other);
+				PRT("\t\t\tvna_name: %s\n",
+				    get_string(ed, s->link, vna->vna_name));
+				PRT("\t\t\tvna_next: %u\n", vna->vna_next);
+			}
+			if (vna->vna_next == 0)
+				break;
+			buf2 += vna->vna_next;
+		}
+		if (vn->vn_next == 0)
+			break;
+		buf += vn->vn_next;
+	}
+}
+
+/*
+ * Dump the symbol-versioning sections.
+ */
+static void
+elf_print_symver(struct elfdump *ed)
+{
+	struct section	*s;
+	size_t		 i;
+
+	for (i = 0; i < ed->shnum; i++) {
+		s = &ed->sl[i];
+		if (!STAILQ_EMPTY(&ed->snl) && !find_name(ed, s->name))
+			continue;
+		if (s->type == SHT_SUNW_verdef)
+			elf_print_verdef(ed, s);
+		if (s->type == SHT_SUNW_verneed)
+			elf_print_verneed(ed, s);
+	}
+}
+
+/*
+ * Dump the ELF checksum. See gelf_checksum(3) for details.
+ */
+static void
+elf_print_checksum(struct elfdump *ed)
+{
+
+	if (!STAILQ_EMPTY(&ed->snl))
+		return;
+
+	PRT("\nelf checksum: %#lx\n", gelf_checksum(ed->elf));
+}
+
+#define	USAGE_MESSAGE	"\
+Usage: %s [options] file...\n\
+  Display information about ELF objects and ar(1) archives.\n\n\
+  Options:\n\
+  -a                        Show all information.\n\
+  -c                        Show shared headers.\n\
+  -d                        Show dynamic symbols.\n\
+  -e                        Show the ELF header.\n\
+  -G                        Show the GOT.\n\
+  -H | --help               Show a usage message and exit.\n\
+  -h                        Show hash values.\n\
+  -i                        Show the dynamic interpreter.\n\
+  -k                        Show the ELF checksum.\n\
+  -n                        Show the contents of note sections.\n\
+  -N NAME                   Show the section named \"NAME\".\n\
+  -p                        Show the program header.\n\
+  -r                        Show relocations.\n\
+  -s                        Show the symbol table.\n\
+  -S                        Use the Solaris elfdump format.\n\
+  -v                        Show symbol-versioning information.\n\
+  -V | --version            Print a version identifier and exit.\n\
+  -w FILE                   Write output to \"FILE\".\n"
+
+static void
+usage(void)
+{
+	fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
+	exit(EXIT_FAILURE);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/elfdump/os.NetBSD.mk	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,2 @@
+# TODO(#511): Revert after the source tree is -Wconversion clean.
+WARNS=5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/Makefile	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,337 @@
+# $Id: Makefile 3594 2018-04-11 18:26:50Z jkoshy $
+
+TOP=	..
+
+LIB=	dwarf
+
+SRCS=	\
+	dwarf_abbrev.c		\
+	dwarf_arange.c		\
+	dwarf_attr.c		\
+	dwarf_attrval.c		\
+	dwarf_cu.c		\
+	dwarf_dealloc.c		\
+	dwarf_die.c		\
+	dwarf_dump.c		\
+	dwarf_errmsg.c		\
+	dwarf_finish.c		\
+	dwarf_form.c		\
+	dwarf_frame.c		\
+	dwarf_funcs.c		\
+	dwarf_init.c		\
+	dwarf_lineno.c		\
+	dwarf_loclist.c		\
+	dwarf_macinfo.c		\
+	dwarf_pro_arange.c	\
+	dwarf_pro_attr.c	\
+	dwarf_pro_die.c		\
+	dwarf_pro_expr.c	\
+	dwarf_pro_finish.c	\
+	dwarf_pro_frame.c	\
+	dwarf_pro_funcs.c	\
+	dwarf_pro_init.c	\
+	dwarf_pro_lineno.c	\
+	dwarf_pro_macinfo.c	\
+	dwarf_pro_pubnames.c	\
+	dwarf_pro_reloc.c	\
+	dwarf_pro_sections.c	\
+	dwarf_pro_types.c	\
+	dwarf_pro_vars.c	\
+	dwarf_pro_weaks.c	\
+	dwarf_pubnames.c	\
+	dwarf_pubtypes.c	\
+	dwarf_ranges.c		\
+	dwarf_reloc.c		\
+	dwarf_sections.c	\
+	dwarf_seterror.c	\
+	dwarf_str.c		\
+	dwarf_types.c		\
+	dwarf_vars.c		\
+	dwarf_weaks.c		\
+	libdwarf.c		\
+	libdwarf_abbrev.c	\
+	libdwarf_arange.c	\
+	libdwarf_attr.c		\
+	libdwarf_die.c		\
+	libdwarf_error.c	\
+	libdwarf_elf_access.c	\
+	libdwarf_elf_init.c	\
+	libdwarf_frame.c	\
+	libdwarf_info.c		\
+	libdwarf_init.c		\
+	libdwarf_lineno.c	\
+	libdwarf_loc.c		\
+	libdwarf_loclist.c	\
+	libdwarf_macinfo.c	\
+	libdwarf_nametbl.c	\
+	libdwarf_ranges.c	\
+	libdwarf_reloc.c	\
+	libdwarf_rw.c		\
+	libdwarf_sections.c	\
+	libdwarf_str.c
+
+INCS=		dwarf.h libdwarf.h
+INCSDIR=	/usr/include
+
+GENSRCS=	dwarf_pubnames.c dwarf_pubtypes.c dwarf_weaks.c \
+		dwarf_funcs.c dwarf_vars.c dwarf_types.c	\
+		dwarf_pro_pubnames.c dwarf_pro_weaks.c		\
+		dwarf_pro_funcs.c dwarf_pro_types.c		\
+		dwarf_pro_vars.c
+CLEANFILES=	${GENSRCS}
+
+SHLIB_MAJOR=	3
+
+WARNS?=	6
+
+LDADD+=		-lelf
+
+MAN=	dwarf.3                                         \
+	dwarf_add_arange.3				\
+	dwarf_add_AT_comp_dir.3				\
+	dwarf_add_AT_const_value_string.3		\
+	dwarf_add_AT_dataref.3				\
+	dwarf_add_AT_flag.3				\
+	dwarf_add_AT_location_expr.3			\
+	dwarf_add_AT_name.3				\
+	dwarf_add_AT_producer.3				\
+	dwarf_add_AT_ref_address.3			\
+	dwarf_add_AT_reference.3			\
+	dwarf_add_AT_signed_const.3			\
+	dwarf_add_AT_string.3				\
+	dwarf_add_AT_targ_address.3			\
+	dwarf_add_die_to_debug.3			\
+	dwarf_add_directory_decl.3			\
+	dwarf_add_expr_addr.3				\
+	dwarf_add_expr_gen.3				\
+	dwarf_add_fde_inst.3				\
+	dwarf_add_file_decl.3				\
+	dwarf_add_frame_cie.3				\
+	dwarf_add_frame_fde.3				\
+	dwarf_add_funcname.3				\
+	dwarf_add_line_entry.3				\
+	dwarf_add_pubname.3				\
+	dwarf_add_typename.3				\
+	dwarf_add_varname.3				\
+	dwarf_add_weakname.3				\
+	dwarf_attr.3					\
+	dwarf_attrlist.3				\
+	dwarf_attroffset.3				\
+	dwarf_attrval_signed.3				\
+	dwarf_child.3					\
+	dwarf_dealloc.3					\
+	dwarf_def_macro.3				\
+	dwarf_die_abbrev_code.3				\
+	dwarf_die_link.3				\
+	dwarf_diename.3					\
+	dwarf_dieoffset.3				\
+	dwarf_end_macro_file.3				\
+	dwarf_errmsg.3					\
+	dwarf_errno.3					\
+	dwarf_expand_frame_instructions.3		\
+	dwarf_expr_current_offset.3			\
+	dwarf_expr_into_block.3				\
+	dwarf_fde_cfa_offset.3				\
+	dwarf_find_macro_value_start.3			\
+	dwarf_finish.3					\
+	dwarf_formaddr.3				\
+	dwarf_formblock.3				\
+	dwarf_formexprloc.3				\
+	dwarf_formflag.3				\
+	dwarf_formref.3					\
+	dwarf_formsig8.3				\
+	dwarf_formstring.3				\
+	dwarf_formudata.3				\
+	dwarf_get_abbrev.3				\
+	dwarf_get_abbrev_children_flag.3		\
+	dwarf_get_abbrev_code.3				\
+	dwarf_get_abbrev_entry.3			\
+	dwarf_get_abbrev_tag.3				\
+	dwarf_get_address_size.3			\
+	dwarf_get_arange.3				\
+	dwarf_get_arange_info.3				\
+	dwarf_get_aranges.3				\
+	dwarf_get_AT_name.3				\
+	dwarf_get_cie_index.3				\
+	dwarf_get_cie_info.3				\
+	dwarf_get_cie_of_fde.3				\
+	dwarf_get_cu_die_offset.3			\
+	dwarf_get_die_infotypes_flag.3			\
+	dwarf_get_elf.3					\
+	dwarf_get_fde_at_pc.3				\
+	dwarf_get_fde_info_for_all_regs.3		\
+	dwarf_get_fde_info_for_all_regs3.3		\
+	dwarf_get_fde_info_for_cfa_reg3.3		\
+	dwarf_get_fde_info_for_reg.3			\
+	dwarf_get_fde_info_for_reg3.3			\
+	dwarf_get_fde_instr_bytes.3			\
+	dwarf_get_fde_list.3				\
+	dwarf_get_fde_n.3				\
+	dwarf_get_fde_range.3				\
+	dwarf_get_form_class.3				\
+	dwarf_get_funcs.3				\
+	dwarf_get_globals.3				\
+	dwarf_get_loclist_entry.3			\
+	dwarf_get_macro_details.3			\
+	dwarf_get_pubtypes.3				\
+	dwarf_get_ranges.3				\
+	dwarf_get_relocation_info.3			\
+	dwarf_get_relocation_info_count.3		\
+	dwarf_get_section_bytes.3			\
+	dwarf_get_section_max_offsets.3			\
+	dwarf_get_str.3					\
+	dwarf_get_types.3				\
+	dwarf_get_vars.3				\
+	dwarf_get_weaks.3				\
+	dwarf_hasattr.3					\
+	dwarf_hasform.3					\
+	dwarf_highpc.3					\
+	dwarf_init.3					\
+	dwarf_lineno.3					\
+	dwarf_lne_end_sequence.3			\
+	dwarf_lne_set_address.3				\
+	dwarf_loclist.3					\
+	dwarf_loclist_from_expr.3			\
+	dwarf_new_die.3					\
+	dwarf_new_expr.3				\
+	dwarf_new_fde.3					\
+	dwarf_next_cu_header.3				\
+	dwarf_next_types_section.3			\
+	dwarf_object_init.3				\
+	dwarf_producer_init.3				\
+	dwarf_producer_set_isa.3			\
+	dwarf_reset_section_bytes.3			\
+	dwarf_seterrarg.3				\
+	dwarf_set_frame_cfa_value.3			\
+	dwarf_set_reloc_application.3			\
+	dwarf_srcfiles.3				\
+	dwarf_srclines.3				\
+	dwarf_start_macro_file.3			\
+	dwarf_tag.3					\
+	dwarf_transform_to_disk_form.3			\
+	dwarf_undef_macro.3				\
+	dwarf_vendor_ext.3				\
+	dwarf_whatattr.3
+
+MLINKS+= \
+	dwarf_add_AT_const_value_string.3 dwarf_add_AT_const_value_signedint.3 \
+	dwarf_add_AT_const_value_string.3 dwarf_add_AT_const_value_unsignedint.3 \
+	dwarf_add_AT_signed_const.3 dwarf_add_AT_unsigned_const.3 \
+	dwarf_add_AT_targ_address.3 dwarf_add_AT_targ_address_b.3 \
+	dwarf_add_arange.3	dwarf_add_arange_b.3	\
+	dwarf_add_expr_addr.3	dwarf_add_expr_addr_b.3	\
+	dwarf_add_frame_fde.3	dwarf_add_frame_fde_b.3	\
+	dwarf_attrval_signed.3	dwarf_attrval_flag.3	\
+	dwarf_attrval_signed.3	dwarf_attrval_string.3	\
+	dwarf_attrval_signed.3	dwarf_attrval_unsigned.3 \
+	dwarf_child.3	dwarf_offdie.3			\
+	dwarf_child.3	dwarf_offdie_b.3		\
+	dwarf_child.3	dwarf_siblingof.3		\
+	dwarf_child.3	dwarf_siblingof_b.3		\
+	dwarf_dealloc.3	dwarf_fde_cie_list_dealloc.3	\
+	dwarf_dealloc.3	dwarf_funcs_dealloc.3		\
+	dwarf_dealloc.3	dwarf_globals_dealloc.3		\
+	dwarf_dealloc.3	dwarf_pubtypes_dealloc.3	\
+	dwarf_dealloc.3	dwarf_types_dealloc.3		\
+	dwarf_dealloc.3	dwarf_vars_dealloc.3		\
+	dwarf_dealloc.3	dwarf_weaks_dealloc.3		\
+	dwarf_dealloc.3	dwarf_ranges_dealloc.3		\
+	dwarf_dealloc.3	dwarf_srclines_dealloc.3	\
+	dwarf_init.3	dwarf_elf_init.3		\
+	dwarf_dieoffset.3	dwarf_die_CU_offset.3	\
+	dwarf_dieoffset.3	dwarf_die_CU_offset_range.3 \
+	dwarf_dieoffset.3	dwarf_get_cu_die_offset_given_cu_header_offset.3 \
+	dwarf_dieoffset.3	dwarf_get_cu_die_offset_given_cu_header_offset_b.3 \
+	dwarf_finish.3		dwarf_object_finish.3	\
+	dwarf_formref.3	dwarf_global_formref.3		\
+	dwarf_formudata.3	dwarf_formsdata.3	\
+	dwarf_get_AT_name.3	dwarf_get_ACCESS_name.3	\
+	dwarf_get_AT_name.3	dwarf_get_ATE_name.3	\
+	dwarf_get_AT_name.3	dwarf_get_CC_name.3	\
+	dwarf_get_AT_name.3	dwarf_get_CFA_name.3	\
+	dwarf_get_AT_name.3	dwarf_get_CHILDREN_name.3 \
+	dwarf_get_AT_name.3	dwarf_get_DS_name.3	\
+	dwarf_get_AT_name.3	dwarf_get_DSC_name.3	\
+	dwarf_get_AT_name.3	dwarf_get_EH_name.3	\
+	dwarf_get_AT_name.3	dwarf_get_END_name.3	\
+	dwarf_get_AT_name.3	dwarf_get_FORM_name.3	\
+	dwarf_get_AT_name.3	dwarf_get_ID_name.3	\
+	dwarf_get_AT_name.3	dwarf_get_INL_name.3	\
+	dwarf_get_AT_name.3	dwarf_get_LANG_name.3	\
+	dwarf_get_AT_name.3	dwarf_get_LNE_name.3	\
+	dwarf_get_AT_name.3	dwarf_get_LNS_name.3	\
+	dwarf_get_AT_name.3	dwarf_get_MACINFO_name.3 \
+	dwarf_get_AT_name.3	dwarf_get_OP_name.3	\
+	dwarf_get_AT_name.3	dwarf_get_ORD_name.3	\
+	dwarf_get_AT_name.3	dwarf_get_TAG_name.3	\
+	dwarf_get_AT_name.3	dwarf_get_VIRTUALITY_name.3 \
+	dwarf_get_AT_name.3	dwarf_get_VIS_name.3	\
+	dwarf_get_cu_die_offset.3 dwarf_get_arange_cu_header_offset.3 \
+	dwarf_get_fde_list.3	dwarf_get_fde_list_eh.3	\
+	dwarf_get_funcs.3	dwarf_func_die_offset.3	\
+	dwarf_get_funcs.3	dwarf_func_cu_offset.3	\
+	dwarf_get_funcs.3	dwarf_func_name_offsets.3 \
+	dwarf_get_funcs.3	dwarf_funcname.3	\
+	dwarf_get_globals.3	dwarf_global_die_offset.3 \
+	dwarf_get_globals.3	dwarf_global_cu_offset.3 \
+	dwarf_get_globals.3	dwarf_global_name_offsets.3 \
+	dwarf_get_globals.3	dwarf_globname.3	\
+	dwarf_get_pubtypes.3	dwarf_pubtype_die_offset.3 \
+	dwarf_get_pubtypes.3	dwarf_pubtype_cu_offset.3 \
+	dwarf_get_pubtypes.3	dwarf_pubtype_name_offsets.3 \
+	dwarf_get_pubtypes.3	dwarf_pubtypename.3	\
+	dwarf_get_ranges.3	dwarf_get_ranges_a.3	\
+	dwarf_get_section_max_offsets.3 dwarf_get_section_max_offsets_b.3 \
+	dwarf_get_types.3	dwarf_type_die_offset.3	\
+	dwarf_get_types.3	dwarf_type_cu_offset.3	\
+	dwarf_get_types.3	dwarf_type_name_offsets.3 \
+	dwarf_get_types.3	dwarf_typename.3	\
+	dwarf_get_vars.3	dwarf_var_die_offset.3	\
+	dwarf_get_vars.3	dwarf_var_cu_offset.3	\
+	dwarf_get_vars.3	dwarf_var_name_offsets.3 \
+	dwarf_get_vars.3	dwarf_varname.3		\
+	dwarf_get_weaks.3	dwarf_weak_die_offset.3	\
+	dwarf_get_weaks.3	dwarf_weak_cu_offset.3	\
+	dwarf_get_weaks.3	dwarf_weak_name_offsets.3 \
+	dwarf_get_weaks.3	dwarf_weakname.3	\
+	dwarf_hasform.3	dwarf_whatform.3		\
+	dwarf_hasform.3	dwarf_whatform_direct.3		\
+	dwarf_highpc.3	dwarf_arrayorder.3		\
+	dwarf_highpc.3	dwarf_bitoffset.3		\
+	dwarf_highpc.3	dwarf_bitsize.3			\
+	dwarf_highpc.3	dwarf_bytesize.3		\
+	dwarf_highpc.3	dwarf_highpc_b.3		\
+	dwarf_highpc.3	dwarf_lowpc.3			\
+	dwarf_highpc.3	dwarf_srclang.3			\
+	dwarf_lineno.3	dwarf_lineaddr.3		\
+	dwarf_lineno.3	dwarf_linebeginstatement.3	\
+	dwarf_lineno.3	dwarf_lineblock.3		\
+	dwarf_lineno.3	dwarf_lineendsequence.3		\
+	dwarf_lineno.3	dwarf_lineoff.3			\
+	dwarf_lineno.3	dwarf_linesrc.3			\
+	dwarf_lineno.3	dwarf_line_srcfileno.3		\
+	dwarf_loclist.3	dwarf_loclist_n.3		\
+	dwarf_loclist_from_expr.3 dwarf_loclist_from_expr_a.3 \
+	dwarf_loclist_from_expr.3 dwarf_loclist_from_expr_b.3 \
+	dwarf_next_cu_header.3 dwarf_next_cu_header_b.3	\
+	dwarf_next_cu_header.3 dwarf_next_cu_header_c.3	\
+	dwarf_producer_init.3 dwarf_producer_init_b.3	\
+	dwarf_seterrarg.3	dwarf_seterrhand.3	\
+	dwarf_set_frame_cfa_value.3 dwarf_set_frame_rule_initial_value.3 \
+	dwarf_set_frame_cfa_value.3 dwarf_set_frame_rule_table_size.3 \
+	dwarf_set_frame_cfa_value.3 dwarf_set_frame_same_value.3 \
+	dwarf_set_frame_cfa_value.3 dwarf_set_frame_undefined_value.3
+
+dwarf_pubnames.c:	dwarf_nametbl.m4 dwarf_pubnames.m4
+dwarf_pubtypes.c:	dwarf_nametbl.m4 dwarf_pubtypes.m4
+dwarf_weaks.c:		dwarf_nametbl.m4 dwarf_weaks.m4
+dwarf_funcs.c:		dwarf_nametbl.m4 dwarf_funcs.m4
+dwarf_vars.c:		dwarf_nametbl.m4 dwarf_vars.m4
+dwarf_types.c:		dwarf_nametbl.m4 dwarf_types.m4
+dwarf_pro_pubnames.c:	dwarf_pro_nametbl.m4 dwarf_pro_pubnames.m4
+dwarf_pro_weaks.c:	dwarf_pro_nametbl.m4 dwarf_pro_weaks.m4
+dwarf_pro_funcs.c:	dwarf_pro_nametbl.m4 dwarf_pro_funcs.m4
+dwarf_pro_types.c:	dwarf_pro_nametbl.m4 dwarf_pro_types.m4
+dwarf_pro_vars.c:	dwarf_pro_nametbl.m4 dwarf_pro_vars.m4
+
+.include "${TOP}/mk/elftoolchain.lib.mk"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/Version.map	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,239 @@
+/* $Id: Version.map 3085 2014-09-02 22:08:23Z kaiwang27 $ */
+
+R1.0 {
+global:
+	dwarf_add_AT_comp_dir;
+	dwarf_add_AT_const_value_signedint;
+	dwarf_add_AT_const_value_string;
+	dwarf_add_AT_const_value_unsignedint;
+	dwarf_add_AT_dataref;
+	dwarf_add_AT_flag;
+	dwarf_add_AT_location_expr;
+	dwarf_add_AT_name;
+	dwarf_add_AT_producer;
+	dwarf_add_AT_ref_address;
+	dwarf_add_AT_reference;
+	dwarf_add_AT_signed_const;
+	dwarf_add_AT_string;
+	dwarf_add_AT_targ_address;
+	dwarf_add_AT_targ_address_b;
+	dwarf_add_AT_unsigned_const;
+	dwarf_add_arange;
+	dwarf_add_arange_b;
+	dwarf_add_die_to_debug;
+	dwarf_add_directory_decl;
+	dwarf_add_expr_addr;
+	dwarf_add_expr_addr_b;
+	dwarf_add_expr_gen;
+	dwarf_add_fde_inst;
+	dwarf_add_file_decl;
+	dwarf_add_frame_cie;
+	dwarf_add_frame_fde;
+	dwarf_add_frame_fde_b;
+	dwarf_add_funcname;
+	dwarf_add_line_entry;
+	dwarf_add_pubname;
+	dwarf_add_typename;
+	dwarf_add_varname;
+	dwarf_add_weakname;
+	dwarf_arrayorder;
+	dwarf_attr;
+	dwarf_attrlist;
+	dwarf_attroffset;
+	dwarf_attrval_flag;
+	dwarf_attrval_signed;
+	dwarf_attrval_string;
+	dwarf_attrval_unsigned;
+	dwarf_bitoffset;
+	dwarf_bitsize;
+	dwarf_bytesize;
+	dwarf_child;
+	dwarf_dealloc;
+	dwarf_def_macro;
+	dwarf_die_CU_offset;
+	dwarf_die_CU_offset_range;
+	dwarf_die_abbrev_code;
+	dwarf_die_link;
+	dwarf_diename;
+	dwarf_dieoffset;
+	dwarf_elf_init;
+	dwarf_end_macro_file;
+	dwarf_errmsg_;
+	dwarf_expand_frame_instructions;
+	dwarf_expr_current_offset;
+	dwarf_expr_into_block;
+	dwarf_fde_cfa_offset;
+	dwarf_fde_cie_list_dealloc;
+	dwarf_find_macro_value_start;
+	dwarf_finish;
+	dwarf_formaddr;
+	dwarf_formblock;
+	dwarf_formexprloc;
+	dwarf_formflag;
+	dwarf_formref;
+	dwarf_formsdata;
+	dwarf_formsig8;
+	dwarf_formstring;
+	dwarf_formudata;
+	dwarf_func_cu_offset;
+	dwarf_func_die_offset;
+	dwarf_func_name_offsets;
+	dwarf_funcname;
+	dwarf_funcs_dealloc;
+	dwarf_get_ACCESS_name;
+	dwarf_get_ATE_name;
+	dwarf_get_AT_name;
+	dwarf_get_CC_name;
+	dwarf_get_CFA_name;
+	dwarf_get_CHILDREN_name;
+	dwarf_get_DSC_name;
+	dwarf_get_DS_name;
+	dwarf_get_EH_name;
+	dwarf_get_END_name;
+	dwarf_get_FORM_name;
+	dwarf_get_ID_name;
+	dwarf_get_INL_name;
+	dwarf_get_LANG_name;
+	dwarf_get_LNE_name;
+	dwarf_get_LNS_name;
+	dwarf_get_MACINFO_name;
+	dwarf_get_OP_name;
+	dwarf_get_ORD_name;
+	dwarf_get_TAG_name;
+	dwarf_get_VIRTUALITY_name;
+	dwarf_get_VIS_name;
+	dwarf_get_abbrev;
+	dwarf_get_abbrev_children_flag;
+	dwarf_get_abbrev_code;
+	dwarf_get_abbrev_entry;
+	dwarf_get_abbrev_tag;
+	dwarf_get_address_size;
+	dwarf_get_arange;
+	dwarf_get_arange_cu_header_offset;
+	dwarf_get_arange_info;
+	dwarf_get_aranges;
+	dwarf_get_cie_index;
+	dwarf_get_cie_info;
+	dwarf_get_cie_of_fde;
+	dwarf_get_cu_die_offset;
+	dwarf_get_cu_die_offset_given_cu_header_offset;
+	dwarf_get_cu_die_offset_given_cu_header_offset_b;
+	dwarf_get_die_infotypes_flag;
+	dwarf_get_elf;
+	dwarf_get_fde_at_pc;
+	dwarf_get_fde_info_for_all_regs3;
+	dwarf_get_fde_info_for_all_regs;
+	dwarf_get_fde_info_for_cfa_reg3;
+	dwarf_get_fde_info_for_reg3;
+	dwarf_get_fde_info_for_reg;
+	dwarf_get_fde_instr_bytes;
+	dwarf_get_fde_list;
+	dwarf_get_fde_list_eh;
+	dwarf_get_fde_n;
+	dwarf_get_fde_range;
+	dwarf_get_form_class;
+	dwarf_get_funcs;
+	dwarf_get_globals;
+	dwarf_get_loclist_entry;
+	dwarf_get_macro_details;
+	dwarf_get_pubtypes;
+	dwarf_get_ranges;
+	dwarf_get_ranges_a;
+	dwarf_get_relocation_info;
+	dwarf_get_relocation_info_count;
+	dwarf_get_section_bytes;
+	dwarf_get_section_max_offsets;
+	dwarf_get_section_max_offsets_b;
+	dwarf_get_str;
+	dwarf_get_types;
+	dwarf_get_vars;
+	dwarf_get_weaks;
+	dwarf_global_cu_offset;
+	dwarf_global_die_offset;
+	dwarf_global_formref;
+	dwarf_global_name_offsets;
+	dwarf_globals_dealloc;
+	dwarf_globname;
+	dwarf_hasattr;
+	dwarf_hasform;
+	dwarf_highpc;
+	dwarf_highpc_b;
+	dwarf_init;
+	dwarf_line_srcfileno;
+	dwarf_lineaddr;
+	dwarf_linebeginstatement;
+	dwarf_lineblock;
+	dwarf_lineendsequence;
+	dwarf_lineno;
+	dwarf_lineoff;
+	dwarf_linesrc;
+	dwarf_lne_end_sequence;
+	dwarf_lne_set_address;
+	dwarf_loclist;
+	dwarf_loclist_from_expr;
+	dwarf_loclist_from_expr_a;
+	dwarf_loclist_from_expr_b;
+	dwarf_loclist_n;
+	dwarf_lowpc;
+	dwarf_new_die;
+	dwarf_new_expr;
+	dwarf_new_fde;
+	dwarf_next_cu_header;
+	dwarf_next_cu_header_b;
+	dwarf_next_cu_header_c;
+	dwarf_next_types_section;
+	dwarf_object_finish;
+	dwarf_object_init;
+	dwarf_offdie;
+	dwarf_offdie_b;
+	dwarf_producer_finish;
+	dwarf_producer_init;
+	dwarf_producer_init_b;
+	dwarf_producer_set_isa;
+	dwarf_pubtype_cu_offset;
+	dwarf_pubtype_die_offset;
+	dwarf_pubtype_name_offsets;
+	dwarf_pubtypename;
+	dwarf_pubtypes_dealloc;
+	dwarf_ranges_dealloc;
+	dwarf_reset_section_bytes;
+	dwarf_set_frame_cfa_value;
+	dwarf_set_frame_rule_initial_value;
+	dwarf_set_frame_rule_table_size;
+	dwarf_set_frame_same_value;
+	dwarf_set_frame_undefined_value;
+	dwarf_set_reloc_application;
+	dwarf_seterrarg;
+	dwarf_seterrhand;
+	dwarf_siblingof;
+	dwarf_siblingof_b;
+	dwarf_srcfiles;
+	dwarf_srclang;
+	dwarf_srclines;
+	dwarf_srclines_dealloc;
+	dwarf_start_macro_file;
+	dwarf_tag;
+	dwarf_transform_to_disk_form;
+	dwarf_type_cu_offset;
+	dwarf_type_die_offset;
+	dwarf_type_name_offsets;
+	dwarf_typename;
+	dwarf_types_dealloc;
+	dwarf_undef_macro;
+	dwarf_var_cu_offset;
+	dwarf_var_die_offset;
+	dwarf_var_name_offsets;
+	dwarf_varname;
+	dwarf_vars_dealloc;
+	dwarf_vendor_ext;
+	dwarf_weak_cu_offset;
+	dwarf_weak_die_offset;
+	dwarf_weak_name_offsets;
+	dwarf_weakname;
+	dwarf_weaks_dealloc;
+	dwarf_whatattr;
+	dwarf_whatform;
+	dwarf_whatform_direct;
+local:
+	*;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/_libdwarf.h	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,666 @@
+/*-
+ * Copyright (c) 2007 John Birrell (jb@freebsd.org)
+ * Copyright (c) 2009-2014 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: _libdwarf.h 3298 2016-01-09 15:43:31Z jkoshy $
+ */
+
+#ifndef	__LIBDWARF_H_
+#define	__LIBDWARF_H_
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <assert.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gelf.h>
+#include "dwarf.h"
+#include "libdwarf.h"
+#include "uthash.h"
+
+#include "_elftc.h"
+
+#define DWARF_DIE_HASH_SIZE		8191
+
+struct _libdwarf_globals {
+	Dwarf_Handler	errhand;
+	Dwarf_Ptr	errarg;
+	int		applyreloc;
+};
+
+extern struct _libdwarf_globals _libdwarf;
+
+#define	_DWARF_SET_ERROR(_d, _e, _err, _elf_err)			\
+	_dwarf_set_error(_d, _e, _err, _elf_err, __func__, __LINE__)
+#define	DWARF_SET_ERROR(_d, _e, _err)					\
+	_DWARF_SET_ERROR(_d, _e, _err, 0)
+#define	DWARF_SET_ELF_ERROR(_d, _e)					\
+	_DWARF_SET_ERROR(_d, _e, DW_DLE_ELF, elf_errno())
+
+/*
+ * Convenient macros for producer bytes stream generation.
+ */
+#define	WRITE_VALUE(value, bytes)					\
+	dbg->write_alloc(&ds->ds_data, &ds->ds_cap, &ds->ds_size,	\
+	    (value), (bytes), error)
+#define	WRITE_ULEB128(value)						\
+	_dwarf_write_uleb128_alloc(&ds->ds_data, &ds->ds_cap,		\
+	    &ds->ds_size, (value), error)
+#define	WRITE_SLEB128(value)						\
+	_dwarf_write_sleb128_alloc(&ds->ds_data, &ds->ds_cap,		\
+	    &ds->ds_size, (value), error)
+#define	WRITE_STRING(string)						\
+	_dwarf_write_string_alloc(&ds->ds_data, &ds->ds_cap,		\
+	    &ds->ds_size, (string), error)
+#define	WRITE_BLOCK(blk, size)						\
+	_dwarf_write_block_alloc(&ds->ds_data, &ds->ds_cap,		\
+	    &ds->ds_size, (blk), (size), error)
+#define	WRITE_PADDING(byte, cnt)					\
+	_dwarf_write_padding_alloc(&ds->ds_data, &ds->ds_cap,		\
+	    &ds->ds_size, (byte), (cnt), error)
+#define	RCHECK(expr)							\
+	do {								\
+		ret = expr;						\
+		if (ret != DW_DLE_NONE)					\
+			goto gen_fail;					\
+	} while(0)
+
+typedef struct _Dwarf_CU *Dwarf_CU;
+
+struct _Dwarf_AttrDef {
+	Dwarf_Half	ad_attrib;		/* DW_AT_XXX */
+	Dwarf_Half	ad_form;		/* DW_FORM_XXX */
+	uint64_t	ad_offset;		/* Offset in abbrev section. */
+	STAILQ_ENTRY(_Dwarf_AttrDef) ad_next;	/* Next attribute define. */
+};
+
+struct _Dwarf_Attribute {
+	Dwarf_Die		at_die;		/* Ptr to containing DIE. */
+	Dwarf_Die		at_refdie;	/* Ptr to reference DIE. */
+	uint64_t		at_offset;	/* Offset in info section. */
+	Dwarf_Half		at_attrib;	/* DW_AT_XXX */
+	Dwarf_Half		at_form;	/* DW_FORM_XXX */
+	int			at_indirect;	/* Has indirect form. */
+	union {
+		uint64_t	u64;		/* Unsigned value. */
+		int64_t		s64;		/* Signed value. */
+		char		*s;   		/* String. */
+		uint8_t		*u8p;		/* Block data. */
+	} u[2];					/* Value. */
+	Dwarf_Block		at_block;	/* Block. */
+	Dwarf_Locdesc		*at_ld;		/* at value is locdesc. */
+	Dwarf_P_Expr		at_expr;	/* at value is expr. */
+	uint64_t		at_relsym;	/* Relocation symbol index. */
+	const char		*at_relsec;	/* Rel. to dwarf section. */
+	STAILQ_ENTRY(_Dwarf_Attribute) at_next;	/* Next attribute. */
+};
+
+struct _Dwarf_Abbrev {
+	uint64_t	ab_entry;	/* Abbrev entry. */
+	uint64_t	ab_tag;		/* Tag: DW_TAG_ */
+	uint8_t		ab_children;	/* DW_CHILDREN_no or DW_CHILDREN_yes */
+	uint64_t	ab_offset;	/* Offset in abbrev section. */
+	uint64_t	ab_length;	/* Length of this abbrev entry. */
+	uint64_t	ab_atnum;	/* Number of attribute defines. */
+	UT_hash_handle	ab_hh;		/* Uthash handle. */
+	STAILQ_HEAD(, _Dwarf_AttrDef) ab_attrdef; /* List of attribute defs. */
+};
+
+struct _Dwarf_Die {
+	Dwarf_Die	die_parent;	/* Parent DIE. */
+	Dwarf_Die	die_child;	/* First child DIE. */
+	Dwarf_Die	die_left;	/* Left sibling DIE. */
+	Dwarf_Die	die_right;	/* Right sibling DIE. */
+	uint64_t	die_offset;	/* DIE offset in section. */
+	uint64_t	die_next_off;	/* Next DIE offset in section. */
+	uint64_t	die_abnum;	/* Abbrev number. */
+	Dwarf_Abbrev	die_ab;		/* Abbrev pointer. */
+	Dwarf_Tag	die_tag;	/* DW_TAG_ */
+	Dwarf_Debug	die_dbg;	/* Dwarf_Debug pointer. */
+	Dwarf_CU	die_cu;		/* Compilation unit pointer. */
+	char		*die_name;	/* Ptr to the name string. */
+	Dwarf_Attribute	*die_attrarray;	/* Array of attributes. */
+	STAILQ_HEAD(, _Dwarf_Attribute)	die_attr; /* List of attributes. */
+	STAILQ_ENTRY(_Dwarf_Die) die_pro_next; /* Next die in pro-die list. */
+};
+
+struct _Dwarf_P_Expr_Entry {
+	Dwarf_Loc	ee_loc;		/* Location expression. */
+	Dwarf_Unsigned	ee_sym;		/* Optional related reloc sym index. */
+	STAILQ_ENTRY(_Dwarf_P_Expr_Entry) ee_next; /* Next entry in list. */
+};
+
+struct _Dwarf_P_Expr {
+	Dwarf_Debug	pe_dbg;		/* Dwarf_Debug pointer. */
+	uint8_t		*pe_block;	/* Expression block data. */
+	int		pe_invalid;	/* Block data is up-to-date or not. */
+	Dwarf_Unsigned	pe_length;	/* Length of the block. */
+	STAILQ_HEAD(, _Dwarf_P_Expr_Entry) pe_eelist; /* List of entries. */
+	STAILQ_ENTRY(_Dwarf_P_Expr) pe_next; /* Next expr in list. */
+};
+
+struct _Dwarf_Line {
+	Dwarf_LineInfo	ln_li;		/* Ptr to line info. */
+	Dwarf_Addr	ln_addr;	/* Line address. */
+	Dwarf_Unsigned	ln_symndx;	/* Symbol index for relocation. */
+	Dwarf_Unsigned	ln_fileno;	/* File number. */
+	Dwarf_Unsigned	ln_lineno;	/* Line number. */
+	Dwarf_Signed	ln_column;	/* Column number. */
+	Dwarf_Bool	ln_bblock;	/* Basic block flag. */
+	Dwarf_Bool	ln_stmt;	/* Begin statement flag. */
+	Dwarf_Bool	ln_endseq;	/* End sequence flag. */
+	STAILQ_ENTRY(_Dwarf_Line) ln_next; /* Next line in list. */
+};
+
+struct _Dwarf_LineFile {
+	char		*lf_fname;	/* Filename. */
+	char		*lf_fullpath;	/* Full pathname of the file. */
+	Dwarf_Unsigned	lf_dirndx;	/* Dir index. */
+	Dwarf_Unsigned	lf_mtime;	/* Modification time. */
+	Dwarf_Unsigned	lf_size;	/* File size. */
+	STAILQ_ENTRY(_Dwarf_LineFile) lf_next; /* Next file in list. */
+};
+
+struct _Dwarf_LineInfo {
+	Dwarf_Unsigned	li_length;	/* Length of line info data. */
+	Dwarf_Half	li_version;	/* Version of line info. */
+	Dwarf_Unsigned	li_hdrlen;	/* Length of line info header. */
+	Dwarf_Small	li_minlen;	/* Minimum instrutction length. */
+	Dwarf_Small	li_maxop;	/* Maximum operations per inst. */
+	Dwarf_Small	li_defstmt;	/* Default value of is_stmt. */
+	int8_t		li_lbase;    	/* Line base for special opcode. */
+	Dwarf_Small	li_lrange;    	/* Line range for special opcode. */
+	Dwarf_Small	li_opbase;	/* Fisrt std opcode number. */
+	Dwarf_Small	*li_oplen;	/* Array of std opcode len. */
+	char		**li_incdirs;	/* Array of include dirs. */
+	Dwarf_Unsigned	li_inclen;	/* Length of inc dir array. */
+	char		**li_lfnarray;	/* Array of file names. */
+	Dwarf_Unsigned	li_lflen;	/* Length of filename array. */
+	STAILQ_HEAD(, _Dwarf_LineFile) li_lflist; /* List of files. */
+	Dwarf_Line	*li_lnarray;	/* Array of lines. */
+	Dwarf_Unsigned	li_lnlen;	/* Length of the line array. */
+	STAILQ_HEAD(, _Dwarf_Line) li_lnlist; /* List of lines. */
+};
+
+struct _Dwarf_NamePair {
+	Dwarf_NameTbl	np_nt;		/* Ptr to containing name table. */
+	Dwarf_Die	np_die;		/* Ptr to Ref. Die. */
+	Dwarf_Unsigned	np_offset;	/* Offset in CU. */
+	char		*np_name;	/* Object/Type name. */
+	STAILQ_ENTRY(_Dwarf_NamePair) np_next; /* Next pair in the list. */
+};
+
+struct _Dwarf_NameTbl {
+	Dwarf_Unsigned	nt_length;	/* Name lookup table length. */
+	Dwarf_Half	nt_version;	/* Name lookup table version. */
+	Dwarf_CU	nt_cu;		/* Ptr to Ref. CU. */
+	Dwarf_Off	nt_cu_offset;	/* Ref. CU offset in .debug_info */
+	Dwarf_Unsigned	nt_cu_length;	/* Ref. CU length. */
+	STAILQ_HEAD(, _Dwarf_NamePair) nt_nplist; /* List of offset+name pairs. */
+	STAILQ_ENTRY(_Dwarf_NameTbl) nt_next; /* Next name table in the list. */
+};
+
+struct _Dwarf_NameSec {
+	STAILQ_HEAD(, _Dwarf_NameTbl) ns_ntlist; /* List of name tables. */
+	Dwarf_NamePair	*ns_array;	/* Array of pairs of all tables. */
+	Dwarf_Unsigned	ns_len;		/* Length of the pair array. */
+};
+
+struct _Dwarf_Fde {
+	Dwarf_Debug	fde_dbg;	/* Ptr to containing dbg. */
+	Dwarf_Cie	fde_cie;	/* Ptr to associated CIE. */
+	Dwarf_FrameSec	fde_fs;		/* Ptr to containing .debug_frame. */
+	Dwarf_Ptr	fde_addr;	/* Ptr to start of the FDE. */
+	Dwarf_Unsigned	fde_offset;	/* Offset of the FDE. */
+	Dwarf_Unsigned	fde_length;	/* Length of the FDE. */
+	Dwarf_Unsigned	fde_cieoff;	/* Offset of associated CIE. */
+	Dwarf_Unsigned	fde_initloc;	/* Initial location. */
+	Dwarf_Unsigned	fde_adrange;	/* Address range. */
+	Dwarf_Unsigned	fde_auglen;	/* Augmentation length. */
+	uint8_t		*fde_augdata;	/* Augmentation data. */
+	uint8_t		*fde_inst;	/* Instructions. */
+	Dwarf_Unsigned	fde_instlen;	/* Length of instructions. */
+	Dwarf_Unsigned	fde_instcap;	/* Capacity of inst buffer. */
+	Dwarf_Unsigned	fde_symndx;	/* Symbol index for relocation. */
+	Dwarf_Unsigned	fde_esymndx;	/* End symbol index for relocation. */
+	Dwarf_Addr	fde_eoff;	/* Offset from the end symbol. */
+	STAILQ_ENTRY(_Dwarf_Fde) fde_next; /* Next FDE in list. */
+};
+
+struct _Dwarf_Cie {
+	Dwarf_Debug	cie_dbg;	/* Ptr to containing dbg. */
+	Dwarf_Unsigned	cie_index;	/* Index of the CIE. */
+	Dwarf_Unsigned	cie_offset;	/* Offset of the CIE. */
+	Dwarf_Unsigned	cie_length;	/* Length of the CIE. */
+	Dwarf_Half	cie_version;	/* CIE version. */
+	uint8_t		*cie_augment;	/* CIE augmentation (UTF-8). */
+	Dwarf_Unsigned	cie_ehdata;	/* Optional EH Data. */
+	uint8_t		cie_addrsize;	/* Address size. (DWARF4) */
+	uint8_t		cie_segmentsize; /* Segment size. (DWARF4) */
+	Dwarf_Unsigned	cie_caf;	/* Code alignment factor. */
+	Dwarf_Signed	cie_daf;	/* Data alignment factor. */
+	Dwarf_Unsigned	cie_ra;		/* Return address register. */
+	Dwarf_Unsigned	cie_auglen;	/* Augmentation length. */
+	uint8_t		*cie_augdata;	/* Augmentation data; */
+	uint8_t		cie_fde_encode; /* FDE PC start/range encode. */
+	Dwarf_Ptr	cie_initinst;	/* Initial instructions. */
+	Dwarf_Unsigned	cie_instlen;	/* Length of init instructions. */
+	STAILQ_ENTRY(_Dwarf_Cie) cie_next;  /* Next CIE in list. */
+};
+
+struct _Dwarf_FrameSec {
+	STAILQ_HEAD(, _Dwarf_Cie) fs_cielist; /* List of CIE. */
+	STAILQ_HEAD(, _Dwarf_Fde) fs_fdelist; /* List of FDE. */
+	Dwarf_Cie	*fs_ciearray;	/* Array of CIE. */
+	Dwarf_Unsigned	fs_cielen;	/* Length of CIE array. */
+	Dwarf_Fde	*fs_fdearray;	/* Array of FDE.*/
+	Dwarf_Unsigned	fs_fdelen;	/* Length of FDE array. */
+};
+
+struct _Dwarf_Arange {
+	Dwarf_ArangeSet	ar_as;		/* Ptr to the set it belongs to. */
+	Dwarf_Unsigned	ar_address;	/* Start PC. */
+	Dwarf_Unsigned	ar_range;	/* PC range. */
+	Dwarf_Unsigned	ar_symndx;	/* First symbol index for reloc. */
+	Dwarf_Unsigned	ar_esymndx;	/* Second symbol index for reloc. */
+	Dwarf_Addr	ar_eoff;	/* Offset from second symbol. */
+	STAILQ_ENTRY(_Dwarf_Arange) ar_next; /* Next arange in list. */
+};
+
+struct _Dwarf_ArangeSet {
+	Dwarf_Unsigned	as_length;	/* Length of the arange set. */
+	Dwarf_Half	as_version;	/* Version of the arange set. */
+	Dwarf_Off	as_cu_offset;	/* Offset of associated CU. */
+	Dwarf_CU	as_cu;		/* Ptr to associated CU. */
+	Dwarf_Small	as_addrsz;	/* Target address size. */
+	Dwarf_Small	as_segsz;	/* Target segment size. */
+	STAILQ_HEAD (, _Dwarf_Arange) as_arlist; /* List of ae entries. */
+	STAILQ_ENTRY(_Dwarf_ArangeSet) as_next; /* Next set in list. */
+};
+
+struct _Dwarf_MacroSet {
+	Dwarf_Macro_Details *ms_mdlist; /* Array of macinfo entries. */
+	Dwarf_Unsigned	ms_cnt;		/* Length of the array. */
+	STAILQ_ENTRY(_Dwarf_MacroSet) ms_next; /* Next set in list. */
+};
+
+struct _Dwarf_Rangelist {
+	Dwarf_CU	rl_cu;		/* Ptr to associated CU. */
+	Dwarf_Unsigned	rl_offset;	/* Offset of the rangelist. */
+	Dwarf_Ranges	*rl_rgarray;	/* Array of ranges. */
+	Dwarf_Unsigned	rl_rglen;	/* Length of the ranges array. */
+	STAILQ_ENTRY(_Dwarf_Rangelist) rl_next; /* Next rangelist in list. */
+};
+
+struct _Dwarf_CU {
+	Dwarf_Debug	cu_dbg;		/* Ptr to containing dbg. */
+	Dwarf_Off	cu_offset;	/* Offset to the this CU. */
+	uint32_t	cu_length;	/* Length of CU data. */
+	uint16_t	cu_length_size; /* Size in bytes of the length field. */
+	uint16_t	cu_version;	/* DWARF version. */
+	uint64_t	cu_abbrev_offset; /* Offset into .debug_abbrev. */
+	uint64_t	cu_abbrev_offset_cur; /* Current abbrev offset. */
+	int		cu_abbrev_loaded; /* Abbrev table parsed. */
+	uint64_t	cu_abbrev_cnt;	/* Abbrev entry count. */
+	uint64_t	cu_lineno_offset; /* Offset into .debug_lineno. */
+	uint8_t		cu_pointer_size;/* Number of bytes in pointer. */
+	uint8_t		cu_dwarf_size;	/* CU section dwarf size. */
+	Dwarf_Sig8	cu_type_sig;	/* Type unit's signature. */
+	uint64_t	cu_type_offset; /* Type unit's type offset. */
+	Dwarf_Off	cu_next_offset; /* Offset to the next CU. */
+	uint64_t	cu_1st_offset;	/* First DIE offset. */
+	int		cu_pass2;	/* Two pass DIE traverse. */
+	Dwarf_LineInfo	cu_lineinfo;	/* Ptr to Dwarf_LineInfo. */
+	Dwarf_Abbrev	cu_abbrev_hash; /* Abbrev hash table. */
+	Dwarf_Bool	cu_is_info;	/* Compilation/type unit flag. */
+	STAILQ_ENTRY(_Dwarf_CU) cu_next; /* Next compilation unit. */
+};
+
+typedef struct _Dwarf_Section {
+	const char	*ds_name;	/* Section name. */
+	Dwarf_Small	*ds_data;	/* Section data. */
+	Dwarf_Unsigned	ds_addr;	/* Section virtual addr. */
+	Dwarf_Unsigned	ds_size;	/* Section size. */
+} Dwarf_Section;
+
+typedef struct _Dwarf_P_Section {
+	char		*ds_name;	/* Section name. */
+	Dwarf_Small	*ds_data;	/* Section data. */
+	Dwarf_Unsigned	ds_size;	/* Section size. */
+	Dwarf_Unsigned	ds_cap;		/* Section capacity. */
+	Dwarf_Unsigned	ds_ndx;		/* ELF section index. */
+	Dwarf_Unsigned	ds_symndx;	/* Section symbol index. (for reloc) */
+	STAILQ_ENTRY(_Dwarf_P_Section) ds_next; /* Next section in the list. */
+} *Dwarf_P_Section;
+
+typedef struct _Dwarf_Rel_Entry {
+	unsigned char	dre_type;	/* Reloc type. */
+	unsigned char	dre_length;	/* Reloc storage unit length. */
+	Dwarf_Unsigned	dre_offset;	/* Reloc storage unit offset. */
+	Dwarf_Unsigned	dre_addend;	/* Reloc addend. */
+	Dwarf_Unsigned	dre_symndx;	/* Reloc symbol index. */
+	const char	*dre_secname;	/* Refer to some debug section. */
+	STAILQ_ENTRY(_Dwarf_Rel_Entry) dre_next; /* Next reloc entry. */
+} *Dwarf_Rel_Entry;
+
+typedef struct _Dwarf_Rel_Section {
+	struct _Dwarf_P_Section *drs_ds; /* Ptr to actual reloc ELF section. */
+	struct _Dwarf_P_Section *drs_ref; /* Which debug section it refers. */
+	struct Dwarf_Relocation_Data_s *drs_drd; /* Reloc data array. */
+	STAILQ_HEAD(, _Dwarf_Rel_Entry) drs_dre; /* Reloc entry list. */
+	Dwarf_Unsigned	drs_drecnt;	/* Count of entries. */
+	Dwarf_Unsigned	drs_size;	/* Size of ELF section in bytes. */
+	int		drs_addend;	/* Elf_Rel or Elf_Rela */
+	STAILQ_ENTRY(_Dwarf_Rel_Section) drs_next; /* Next reloc section. */
+} *Dwarf_Rel_Section;
+
+typedef struct {
+	Elf_Data *ed_data;
+	void *ed_alloc;
+} Dwarf_Elf_Data;
+
+typedef struct {
+	Elf		*eo_elf;
+	GElf_Ehdr	eo_ehdr;
+	GElf_Shdr	*eo_shdr;
+	Dwarf_Elf_Data	*eo_data;
+	Dwarf_Unsigned	eo_seccnt;
+	size_t		eo_strndx;
+	Dwarf_Obj_Access_Methods eo_methods;
+} Dwarf_Elf_Object;
+
+struct _Dwarf_Debug {
+	Dwarf_Obj_Access_Interface *dbg_iface;
+	Dwarf_Section	*dbg_section;	/* Dwarf section list. */
+	Dwarf_Section	*dbg_info_sec;	/* Pointer to info section. */
+	Dwarf_Off	dbg_info_off;	/* Current info section offset. */
+	Dwarf_Section	*dbg_types_sec; /* Pointer to type section. */
+	Dwarf_Off	dbg_types_off;	/* Current types section offset. */
+	Dwarf_Unsigned	dbg_seccnt;	/* Total number of dwarf sections. */
+	int		dbg_mode;	/* Access mode. */
+	int		dbg_pointer_size; /* Object address size. */
+	int		dbg_offset_size;  /* DWARF offset size. */
+	int		dbg_info_loaded; /* Flag indicating all CU loaded. */
+	int		dbg_types_loaded; /* Flag indicating all TU loaded. */
+	Dwarf_Half	dbg_machine;	/* ELF machine architecture. */
+	Dwarf_Handler	dbg_errhand;	/* Error handler. */
+	Dwarf_Ptr	dbg_errarg;	/* Argument to the error handler. */
+	STAILQ_HEAD(, _Dwarf_CU) dbg_cu;/* List of compilation units. */
+	STAILQ_HEAD(, _Dwarf_CU) dbg_tu;/* List of type units. */
+	Dwarf_CU	dbg_cu_current; /* Ptr to the current CU. */
+	Dwarf_CU	dbg_tu_current; /* Ptr to the current TU. */
+	Dwarf_NameSec	dbg_globals;	/* Ptr to pubnames lookup section. */
+	Dwarf_NameSec	dbg_pubtypes;	/* Ptr to pubtypes lookup section. */
+	Dwarf_NameSec	dbg_weaks;	/* Ptr to weaknames lookup section. */
+	Dwarf_NameSec	dbg_funcs;	/* Ptr to static funcs lookup sect. */
+	Dwarf_NameSec	dbg_vars;	/* Ptr to static vars lookup sect. */
+	Dwarf_NameSec	dbg_types;	/* Ptr to types lookup section. */
+	Dwarf_FrameSec	dbg_frame;	/* Ptr to .debug_frame section. */
+	Dwarf_FrameSec	dbg_eh_frame;	/* Ptr to .eh_frame section. */
+	STAILQ_HEAD(, _Dwarf_ArangeSet) dbg_aslist; /* List of arange set. */
+	Dwarf_Arange	*dbg_arange_array; /* Array of arange. */
+	Dwarf_Unsigned	dbg_arange_cnt;	/* Length of the arange array. */
+	char		*dbg_strtab;	/* Dwarf string table. */
+	Dwarf_Unsigned	dbg_strtab_cap; /* Dwarf string table capacity. */
+	Dwarf_Unsigned	dbg_strtab_size; /* Dwarf string table size. */
+	STAILQ_HEAD(, _Dwarf_MacroSet) dbg_mslist; /* List of macro set. */
+	STAILQ_HEAD(, _Dwarf_Rangelist) dbg_rllist; /* List of rangelist. */
+	uint64_t	(*read)(uint8_t *, uint64_t *, int);
+	void		(*write)(uint8_t *, uint64_t *, uint64_t, int);
+	int		(*write_alloc)(uint8_t **, uint64_t *, uint64_t *,
+			    uint64_t, int, Dwarf_Error *);
+	uint64_t	(*decode)(uint8_t **, int);
+
+	Dwarf_Half	dbg_frame_rule_table_size;
+	Dwarf_Half	dbg_frame_rule_initial_value;
+	Dwarf_Half	dbg_frame_cfa_value;
+	Dwarf_Half	dbg_frame_same_value;
+	Dwarf_Half	dbg_frame_undefined_value;
+
+	Dwarf_Regtable3	*dbg_internal_reg_table;
+
+	/*
+	 * Fields used by libdwarf producer.
+	 */
+
+	Dwarf_Unsigned	dbgp_flags;
+	Dwarf_Unsigned	dbgp_isa;
+	Dwarf_Callback_Func dbgp_func;
+	Dwarf_Callback_Func_b dbgp_func_b;
+	Dwarf_Die	dbgp_root_die;
+	STAILQ_HEAD(, _Dwarf_Die) dbgp_dielist;
+	STAILQ_HEAD(, _Dwarf_P_Expr) dbgp_pelist;
+	Dwarf_LineInfo	dbgp_lineinfo;
+	Dwarf_ArangeSet dbgp_as;
+	Dwarf_Macro_Details *dbgp_mdlist;
+	Dwarf_Unsigned	dbgp_mdcnt;
+	STAILQ_HEAD(, _Dwarf_Cie) dbgp_cielist;
+	STAILQ_HEAD(, _Dwarf_Fde) dbgp_fdelist;
+	Dwarf_Unsigned	dbgp_cielen;
+	Dwarf_Unsigned	dbgp_fdelen;
+	Dwarf_NameTbl	dbgp_pubs;
+	Dwarf_NameTbl	dbgp_weaks;
+	Dwarf_NameTbl	dbgp_funcs;
+	Dwarf_NameTbl	dbgp_types;
+	Dwarf_NameTbl	dbgp_vars;
+	STAILQ_HEAD(, _Dwarf_P_Section) dbgp_seclist;
+	Dwarf_Unsigned	dbgp_seccnt;
+	Dwarf_P_Section	dbgp_secpos;
+	Dwarf_P_Section	dbgp_info;
+	STAILQ_HEAD(, _Dwarf_Rel_Section) dbgp_drslist;
+	Dwarf_Unsigned	dbgp_drscnt;
+	Dwarf_Rel_Section dbgp_drspos;
+};
+
+/*
+ * Internal function prototypes.
+ */
+
+int		_dwarf_abbrev_add(Dwarf_CU, uint64_t, uint64_t, uint8_t,
+		    uint64_t, Dwarf_Abbrev *, Dwarf_Error *);
+void		_dwarf_abbrev_cleanup(Dwarf_CU);
+int		_dwarf_abbrev_find(Dwarf_CU, uint64_t, Dwarf_Abbrev *,
+		    Dwarf_Error *);
+int		_dwarf_abbrev_gen(Dwarf_P_Debug, Dwarf_Error *);
+int		_dwarf_abbrev_parse(Dwarf_Debug, Dwarf_CU, Dwarf_Unsigned *,
+		    Dwarf_Abbrev *, Dwarf_Error *);
+int		_dwarf_add_AT_dataref(Dwarf_P_Debug, Dwarf_P_Die, Dwarf_Half,
+		    Dwarf_Unsigned, Dwarf_Unsigned, const char *,
+		    Dwarf_P_Attribute *, Dwarf_Error *);
+int		_dwarf_add_string_attr(Dwarf_P_Die, Dwarf_P_Attribute *,
+		    Dwarf_Half, char *, Dwarf_Error *);
+int		_dwarf_alloc(Dwarf_Debug *, int, Dwarf_Error *);
+void		_dwarf_arange_cleanup(Dwarf_Debug);
+int		_dwarf_arange_gen(Dwarf_P_Debug, Dwarf_Error *);
+int		_dwarf_arange_init(Dwarf_Debug, Dwarf_Error *);
+void		_dwarf_arange_pro_cleanup(Dwarf_P_Debug);
+int		_dwarf_attr_alloc(Dwarf_Die, Dwarf_Attribute *, Dwarf_Error *);
+Dwarf_Attribute	_dwarf_attr_find(Dwarf_Die, Dwarf_Half);
+int		_dwarf_attr_gen(Dwarf_P_Debug, Dwarf_P_Section, Dwarf_Rel_Section,
+		    Dwarf_CU, Dwarf_Die, int, Dwarf_Error *);
+int		_dwarf_attr_init(Dwarf_Debug, Dwarf_Section *, uint64_t *, int,
+		    Dwarf_CU, Dwarf_Die, Dwarf_AttrDef, uint64_t, int,
+		    Dwarf_Error *);
+int		_dwarf_attrdef_add(Dwarf_Debug, Dwarf_Abbrev, uint64_t,
+		    uint64_t, uint64_t, Dwarf_AttrDef *, Dwarf_Error *);
+uint64_t	_dwarf_decode_lsb(uint8_t **, int);
+uint64_t	_dwarf_decode_msb(uint8_t **, int);
+int64_t		_dwarf_decode_sleb128(uint8_t **);
+uint64_t	_dwarf_decode_uleb128(uint8_t **);
+void		_dwarf_deinit(Dwarf_Debug);
+int		_dwarf_die_alloc(Dwarf_Debug, Dwarf_Die *, Dwarf_Error *);
+int		_dwarf_die_count_links(Dwarf_P_Die, Dwarf_P_Die,
+		    Dwarf_P_Die, Dwarf_P_Die);
+Dwarf_Die	_dwarf_die_find(Dwarf_Die, Dwarf_Unsigned);
+int		_dwarf_die_gen(Dwarf_P_Debug, Dwarf_CU, Dwarf_Rel_Section,
+		    Dwarf_Error *);
+void		_dwarf_die_link(Dwarf_P_Die, Dwarf_P_Die, Dwarf_P_Die,
+		    Dwarf_P_Die, Dwarf_P_Die);
+int		_dwarf_die_parse(Dwarf_Debug, Dwarf_Section *, Dwarf_CU, int,
+		    uint64_t, uint64_t, Dwarf_Die *, int, Dwarf_Error *);
+void		_dwarf_die_pro_cleanup(Dwarf_P_Debug);
+void		_dwarf_elf_deinit(Dwarf_Debug);
+int		_dwarf_elf_init(Dwarf_Debug, Elf *, Dwarf_Error *);
+int		_dwarf_elf_load_section(void *, Dwarf_Half, Dwarf_Small **,
+		    int *);
+Dwarf_Endianness _dwarf_elf_get_byte_order(void *);
+Dwarf_Small	_dwarf_elf_get_length_size(void *);
+Dwarf_Small	_dwarf_elf_get_pointer_size(void *);
+Dwarf_Unsigned	_dwarf_elf_get_section_count(void *);
+int		_dwarf_elf_get_section_info(void *, Dwarf_Half,
+		    Dwarf_Obj_Access_Section *, int *);
+void		_dwarf_expr_cleanup(Dwarf_P_Debug);
+int		_dwarf_expr_into_block(Dwarf_P_Expr, Dwarf_Error *);
+Dwarf_Section	*_dwarf_find_next_types_section(Dwarf_Debug, Dwarf_Section *);
+Dwarf_Section	*_dwarf_find_section(Dwarf_Debug, const char *);
+void		_dwarf_frame_cleanup(Dwarf_Debug);
+int		_dwarf_frame_fde_add_inst(Dwarf_P_Fde, Dwarf_Small,
+		    Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Error *);
+int		_dwarf_frame_gen(Dwarf_P_Debug, Dwarf_Error *);
+int		_dwarf_frame_get_fop(Dwarf_Debug, uint8_t, uint8_t *,
+		    Dwarf_Unsigned, Dwarf_Frame_Op **, Dwarf_Signed *,
+		    Dwarf_Error *);
+int		_dwarf_frame_get_internal_table(Dwarf_Fde, Dwarf_Addr,
+		    Dwarf_Regtable3 **, Dwarf_Addr *, Dwarf_Error *);
+int		_dwarf_frame_interal_table_init(Dwarf_Debug, Dwarf_Error *);
+void		_dwarf_frame_params_init(Dwarf_Debug);
+void		_dwarf_frame_pro_cleanup(Dwarf_P_Debug);
+int		_dwarf_frame_regtable_copy(Dwarf_Debug, Dwarf_Regtable3 **,
+		    Dwarf_Regtable3 *, Dwarf_Error *);
+int		_dwarf_frame_section_load(Dwarf_Debug, Dwarf_Error *);
+int		_dwarf_frame_section_load_eh(Dwarf_Debug, Dwarf_Error *);
+int		_dwarf_generate_sections(Dwarf_P_Debug, Dwarf_Error *);
+Dwarf_Unsigned	_dwarf_get_reloc_type(Dwarf_P_Debug, int);
+int		_dwarf_get_reloc_size(Dwarf_Debug, Dwarf_Unsigned);
+void		_dwarf_info_cleanup(Dwarf_Debug);
+int		_dwarf_info_first_cu(Dwarf_Debug, Dwarf_Error *);
+int		_dwarf_info_first_tu(Dwarf_Debug, Dwarf_Error *);
+int		_dwarf_info_gen(Dwarf_P_Debug, Dwarf_Error *);
+int		_dwarf_info_load(Dwarf_Debug, Dwarf_Bool, Dwarf_Bool,
+		    Dwarf_Error *);
+int		_dwarf_info_next_cu(Dwarf_Debug, Dwarf_Error *);
+int		_dwarf_info_next_tu(Dwarf_Debug, Dwarf_Error *);
+void		_dwarf_info_pro_cleanup(Dwarf_P_Debug);
+int		_dwarf_init(Dwarf_Debug, Dwarf_Unsigned, Dwarf_Handler,
+		    Dwarf_Ptr, Dwarf_Error *);
+int		_dwarf_lineno_gen(Dwarf_P_Debug, Dwarf_Error *);
+int		_dwarf_lineno_init(Dwarf_Die, uint64_t, Dwarf_Error *);
+void		_dwarf_lineno_cleanup(Dwarf_LineInfo);
+void		_dwarf_lineno_pro_cleanup(Dwarf_P_Debug);
+int		_dwarf_loc_fill_locdesc(Dwarf_Debug, Dwarf_Locdesc *,
+		    uint8_t *, uint64_t, uint8_t, uint8_t, uint8_t,
+		    Dwarf_Error *);
+int		_dwarf_loc_fill_locexpr(Dwarf_Debug, Dwarf_Locdesc **,
+		    uint8_t *, uint64_t, uint8_t, uint8_t, uint8_t,
+		    Dwarf_Error *);
+int		_dwarf_loc_add(Dwarf_Die, Dwarf_Attribute, Dwarf_Error *);
+int		_dwarf_loc_expr_add_atom(Dwarf_Debug, uint8_t *, uint8_t *,
+		    Dwarf_Small, Dwarf_Unsigned, Dwarf_Unsigned, int *,
+		    Dwarf_Error *);
+int		_dwarf_loclist_find(Dwarf_Debug, Dwarf_CU, uint64_t,
+		    Dwarf_Locdesc ***, Dwarf_Signed *, Dwarf_Unsigned *,
+		    Dwarf_Error *);
+void		_dwarf_macinfo_cleanup(Dwarf_Debug);
+int		_dwarf_macinfo_gen(Dwarf_P_Debug, Dwarf_Error *);
+int		_dwarf_macinfo_init(Dwarf_Debug, Dwarf_Error *);
+void		_dwarf_macinfo_pro_cleanup(Dwarf_P_Debug);
+int		_dwarf_nametbl_init(Dwarf_Debug, Dwarf_NameSec *,
+		    Dwarf_Section *, Dwarf_Error *);
+void		_dwarf_nametbl_cleanup(Dwarf_NameSec *);
+int		_dwarf_nametbl_gen(Dwarf_P_Debug, const char *, Dwarf_NameTbl,
+		    Dwarf_Error *);
+void		_dwarf_nametbl_pro_cleanup(Dwarf_NameTbl *);
+int		_dwarf_pro_callback(Dwarf_P_Debug, char *, int, Dwarf_Unsigned,
+		    Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Unsigned,
+		    Dwarf_Unsigned *, int *);
+Dwarf_P_Section	_dwarf_pro_find_section(Dwarf_P_Debug, const char *);
+int		_dwarf_ranges_add(Dwarf_Debug, Dwarf_CU, uint64_t,
+		    Dwarf_Rangelist *, Dwarf_Error *);
+void		_dwarf_ranges_cleanup(Dwarf_Debug);
+int		_dwarf_ranges_find(Dwarf_Debug, uint64_t, Dwarf_Rangelist *);
+uint64_t	_dwarf_read_lsb(uint8_t *, uint64_t *, int);
+uint64_t	_dwarf_read_msb(uint8_t *, uint64_t *, int);
+int64_t		_dwarf_read_sleb128(uint8_t *, uint64_t *);
+uint64_t	_dwarf_read_uleb128(uint8_t *, uint64_t *);
+char		*_dwarf_read_string(void *, Dwarf_Unsigned, uint64_t *);
+uint8_t		*_dwarf_read_block(void *, uint64_t *, uint64_t);
+int		_dwarf_reloc_section_finalize(Dwarf_P_Debug, Dwarf_Rel_Section,
+		    Dwarf_Error *);
+int		_dwarf_reloc_entry_add(Dwarf_P_Debug, Dwarf_Rel_Section,
+		    Dwarf_P_Section, unsigned char, unsigned char,
+		    Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Unsigned,
+		    const char *, Dwarf_Error *);
+int		_dwarf_reloc_entry_add_pair(Dwarf_P_Debug, Dwarf_Rel_Section,
+		    Dwarf_P_Section, unsigned char, Dwarf_Unsigned,
+		    Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Unsigned,
+		    Dwarf_Unsigned, Dwarf_Error *);
+void		_dwarf_reloc_cleanup(Dwarf_P_Debug);
+int		_dwarf_reloc_gen(Dwarf_P_Debug, Dwarf_Error *);
+int		_dwarf_reloc_section_gen(Dwarf_P_Debug, Dwarf_Rel_Section,
+		    Dwarf_Error *);
+int		_dwarf_reloc_section_init(Dwarf_P_Debug, Dwarf_Rel_Section *,
+		    Dwarf_P_Section, Dwarf_Error *);
+void		_dwarf_reloc_section_free(Dwarf_P_Debug, Dwarf_Rel_Section *);
+void		_dwarf_section_cleanup(Dwarf_P_Debug);
+int		_dwarf_section_callback(Dwarf_P_Debug, Dwarf_P_Section,
+		    Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Unsigned,
+		    Dwarf_Unsigned, Dwarf_Error *);
+void		_dwarf_section_free(Dwarf_P_Debug, Dwarf_P_Section *);
+int		_dwarf_section_init(Dwarf_P_Debug, Dwarf_P_Section *,
+		    const char *, int, Dwarf_Error *);
+void		_dwarf_set_error(Dwarf_Debug, Dwarf_Error *, int, int,
+		    const char *, int);
+int		_dwarf_strtab_add(Dwarf_Debug, char *, uint64_t *,
+		    Dwarf_Error *);
+void		_dwarf_strtab_cleanup(Dwarf_Debug);
+int		_dwarf_strtab_gen(Dwarf_P_Debug, Dwarf_Error *);
+char		*_dwarf_strtab_get_table(Dwarf_Debug);
+int		_dwarf_strtab_init(Dwarf_Debug, Dwarf_Error *);
+void		_dwarf_type_unit_cleanup(Dwarf_Debug);
+void		_dwarf_write_block(void *, uint64_t *, uint8_t *, uint64_t);
+int		_dwarf_write_block_alloc(uint8_t **, uint64_t *, uint64_t *,
+		    uint8_t *, uint64_t, Dwarf_Error *);
+void		_dwarf_write_lsb(uint8_t *, uint64_t *, uint64_t, int);
+int		_dwarf_write_lsb_alloc(uint8_t **, uint64_t *, uint64_t *,
+		    uint64_t, int, Dwarf_Error *);
+void		_dwarf_write_msb(uint8_t *, uint64_t *, uint64_t, int);
+int		_dwarf_write_msb_alloc(uint8_t **, uint64_t *, uint64_t *,
+		    uint64_t, int, Dwarf_Error *);
+void		_dwarf_write_padding(void *, uint64_t *, uint8_t, uint64_t);
+int		_dwarf_write_padding_alloc(uint8_t **, uint64_t *, uint64_t *,
+		    uint8_t, uint64_t, Dwarf_Error *);
+void		_dwarf_write_string(void *, uint64_t *, char *);
+int		_dwarf_write_string_alloc(uint8_t **, uint64_t *, uint64_t *,
+		    char *, Dwarf_Error *);
+int		_dwarf_write_sleb128(uint8_t *, uint8_t *, int64_t);
+int		_dwarf_write_sleb128_alloc(uint8_t **, uint64_t *, uint64_t *,
+		    int64_t, Dwarf_Error *);
+int		_dwarf_write_uleb128(uint8_t *, uint8_t *, uint64_t);
+int		_dwarf_write_uleb128_alloc(uint8_t **, uint64_t *, uint64_t *,
+		    uint64_t, Dwarf_Error *);
+
+#endif /* !__LIBDWARF_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,751 @@
+.\" Copyright (c) 2011 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: dwarf.3 3295 2016-01-08 22:08:10Z jkoshy $
+.\"
+.Dd December 21, 2014
+.Os
+.Dt DWARF 3
+.Sh NAME
+.Nm dwarf
+.Nd access debugging information in object files
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Sh DESCRIPTION
+.Pp
+The
+.Lb libdwarf
+provides functions that allow an application to read and write debugging
+information in object files.
+The format of debugging information accessible through this API
+is defined by the DWARF standard, see
+.Xr dwarf 4 .
+.Pp
+The
+.Xr DWARF 3
+API has two parts:
+.Bl -bullet
+.It
+A consumer API set allows applications to read existing debug information
+in a program object.
+The functions that comprise the DWARF consumer API are described in
+the section
+.Sx "DWARF Consumer API"
+below.
+.It
+A producer API set that allows applications to add debug information
+to a program object.
+The functions that comprise the DWARF producer API are described in
+the section
+.Sx "DWARF Producer API"
+below.
+.El
+.Pp
+Each function referenced below is further described in its own manual page.
+.Ss Namespace use
+The DWARF library uses the following prefixes:
+.Pp
+.Bl -tag -width ".Li Dwarf_*" -compact
+.It Li DWARF_*
+Used for error numbers and constants.
+.It Li DW_*
+Used for constants.
+.It Li Dwarf_*
+Used for types.
+.It Li dwarf_*
+Used for functions and macros that make up the API.
+.El
+.Ss Data Types
+The DWARF(3) API uses the following data types:
+.Pp
+.Bl -tag -width ".Vt Dwarf_Unsigned" -compact
+.It Vt Dwarf_Abbrev
+Describes DWARF abbreviations.
+.It Vt Dwarf_Addr
+A program address in the target object.
+.It Vt Dwarf_Arange
+Describes address ranges.
+.It Vt Dwarf_Attribute , Vt Dwarf_P_Attribute
+Describes attributes of debugging information entries.
+.It Vt Dwarf_Bool
+Used for boolean states.
+.It Vt Dwarf_Cie , Vt Dwarf_P_Cie
+Describes call information that is common to several frames.
+.It Vt Dwarf_Debug , Vt Dwarf_P_Debug
+An opaque type describing a debug context.
+.It Vt Dwarf_Die , Vt Dwarf_P_Die
+A debugging information entry.
+.It Vt Dwarf_Fde , Vt Dwarf_P_Fde
+A frame descriptor.
+.It Vt Dwarf_Func
+A descriptor representing a function.
+.It Vt Dwarf_Global
+A descriptor representing a global name.
+.It Vt Dwarf_Half
+A 16-bit wide unsigned numeric type.
+.It Vt Dwarf_Handler
+A pointer to an error handling function.
+.It Vt Dwarf_Line
+A descriptor for a source line.
+.It Vt Dwarf_Off
+An unsigned file offset.
+.It Vt Dwarf_P_Expr
+A descriptor for a location expression.
+.It Vt Dwarf_Ptr
+A virtual address used by an application.
+.It Vt Dwarf_Signed
+A 64-bit wide signed numeric type.
+.It Vt Dwarf_Small
+An 8-bit wide unsigned numeric type.
+.It Vt Dwarf_Type
+A descriptor representing a user-specified type.
+.It Vt Dwarf_Unsigned
+A 64-bit wide unsigned numeric type.
+.It Vt Dwarf_Var
+A descriptor representing a static variable.
+.It Vt Dwarf_Weak
+A descriptor representing a weak name.
+.El
+.Ss Error Handling
+.Pp
+Library functions that encounter an error will return with a value
+other than
+.Dv DW_DLV_OK .
+.Pp
+The
+.Lb libdwarf
+allows applications to specify three levels of error handling:
+.Bl -enum -compact
+.It
+Most library functions take a parameter of type
+.Vt Dwarf_Error
+that specifies a location to store an error descriptor in
+case of an error.
+If an error occurs during the execution on an API, and if this
+parameter is non-NULL, then an error descriptor is written to the
+location specified.
+.It
+Otherwise, if the error parameter was NULL, but if an error handler
+was defined for the debug context in use using
+.Xr dwarf_init 3
+or
+.Xr dwarf_seterrhand 3 ,
+then the library will invoke the specified error handler with an error
+descriptor as argument.
+.It
+Otherwise, if a library wide error handler was specified using
+.Xr dwarf_seterrhand 3 ,
+it is called.
+.El
+.Pp
+Error descriptors may be used with
+.Xr dwarf_errmsg 3
+or
+.Xr dwarf_errno 3 .
+.Sh The DWARF Consumer API
+The DWARF consumer API permits applications to read DWARF information in
+an object file.
+.Pp
+The major functional groups of functions in the consumer API are listed
+below.
+.Pp
+.Bl -tag -compact -width "CCCC"
+.It Abbreviations
+.Bl -tag -compact
+.It Fn dwarf_get_abbrev
+Retrieve abbreviation information at a given offset.
+.It Fn dwarf_get_abbrev_children_flag
+Check if an abbreviation has child elements.
+.It Fn dwarf_get_abbrev_code
+Retrieve the abbreviation code for an abbreviation entry descriptor.
+.It Fn dwarf_get_abbrev_entry
+Retrieve abbreviation information for an abbreviation entry
+descriptor.
+.It Fn dwarf_get_abbrev_tag
+Retrieve the tag for an abbreviation entry.
+.El
+.It Addresses
+.Bl -tag -compact
+.It Fn dwarf_get_address_size
+Return the number of bytes needed to represent an address.
+.It Fn dwarf_get_arange
+Search for an address range descriptor covering an address.
+.It Fn dwarf_get_arange_cu_header_offset
+Retrieve the offsets associated with an address range descriptor.
+.It Fn dwarf_get_arange_info
+Extract address range information from a descriptor.
+.It Fn dwarf_get_aranges
+Retrieve program address space mappings.
+.It Fn dwarf_get_cu_die_offset
+Retrieve the offset associated with a compilation unit for an address
+range descriptor.
+.It Fn dwarf_get_ranges , Fn dwarf_get_ranges_a
+Retrieve information about non-contiguous address ranges for
+a debugging information entry.
+.El
+.It Attributes
+.Bl -tag -compact
+.It Fn dwarf_arrayorder
+Retrieve the value of a
+.Dv DW_AT_ordering
+attribute.
+.It Fn dwarf_attr
+Retrieve an attribute descriptor.
+.It Fn dwarf_attrlist
+Retrieve attribute descriptors for a debugging information entry.
+.It Fn dwarf_attroffset
+Retrieve the section-relative offset of an attribute descriptor.
+.It Fn dwarf_attrval_flag
+Retrieve a
+.Dv DW_AT_FORM_flag
+value.
+.It Fn dwarf_attrval_signed
+Retrieve an attribute's value as a signed integral quantity.
+.It Fn dwarf_attrval_string
+Retrieve an attribute's value as a NUL-terminated string.
+.It Fn dwarf_attrval_unsigned
+Retrieve an attribute's value as an unsigned integral quantity.
+.It Fn dwarf_bitoffset ,
+Retrieve the value of a
+.Dv DW_AT_bit_offset
+attribute.
+.It Fn dwarf_bitsize ,
+Retrieve the value of a
+.Dv DW_AT_bit_size
+attribute.
+.It Fn dwarf_bytesize
+Retrieve the value of a
+.Dv DW_AT_byte_size
+attribute.
+.It Fn dwarf_formaddr
+Return the value of an
+.Dv ADDRESS Ns - Ns
+class attribute.
+.It Fn dwarf_formblock
+Return the value of a
+.Dv BLOCK Ns - Ns
+class attribute
+.It Fn dwarf_formexprloc
+Return information about a location expression.
+.It Fn dwarf_formflag
+Retrieve information about a
+.Dv BOOLEAN Ns - Ns
+class attribute.
+.It Fn dwarf_formref , Fn dwarf_global_formref
+Retrieve offsets for
+.Dv REFERENCE Ns - Ns
+class attributes.
+.It Fn dwarf_formsdata , Fn dwarf_formudata
+Retrieve the value of a
+.Dv CONSTANT Ns - Ns
+class attribute.
+.It Fn dwarf_formsig8
+Return the type signature for a DWARF type.
+.It Fn dwarf_formstring
+Retrieve information about a
+.Dv STRING Ns - Ns
+class attribute.
+.It Fn dwarf_get_form_class
+Retrieve the form class for an attribute.
+.It Fn dwarf_hasattr
+Check for the presence of an attribute.
+.It Fn dwarf_hasform
+Check if an attribute has the given form.
+.It Fn dwarf_whatattr
+Retrieve the attribute code for an attribute.
+.It Fn dwarf_whatform , Fn dwarf_whatform_direct
+Retrieve the form of an attribute.
+.El
+.It Call Information Entries and Frame Descriptor Entries
+.Bl -tag -compact
+.It Fn dwarf_get_cie_index
+Retrieve the index for a CIE descriptor.
+.It Fn dwarf_get_cie_info
+Retrieve information from a CIE descriptor.
+.It Fn dwarf_get_cie_of_fde
+Retrieve a CIE descriptor.
+.It Fn dwarf_get_fde_at_pc
+Retrieve an FDE descriptor for an address.
+.It Fn dwarf_get_fde_info_for_all_regs
+Retrieve register rule row.
+.It Fn dwarf_get_fde_info_for_all_regs3
+Retrieve register rule row (revised API).
+.It Fn dwarf_get_fde_info_for_cfa_reg3
+Retrieve a CFA register rule.
+.It Fn dwarf_get_fde_info_for_reg
+Retrieve a register rule.
+.It Fn dwarf_get_fde_info_for_reg3
+Retrieve a register rule (revised API).
+.It Fn dwarf_get_fde_instr_bytes
+Retrieve instructions from an FDE descriptor.
+.It Fn dwarf_get_fde_list , Fn dwarf_get_fde_list_eh
+Retrieve frame information.
+.It Fn dwarf_get_fde_n
+Retrieve an FDE descriptor.
+.It Fn dwarf_get_fde_range
+Retrieve range information from an FDE descriptor.
+.El
+.It Compilation Units
+.Bl -tag -compact
+.It Xo
+.Fn dwarf_get_cu_die_offset_given_cu_header_offset ,
+.Fn dwarf_get_cu_die_offset_given_cu_header_offset_b
+.Xc
+Retrieve the offset of the debugging information entry for a
+compilation or type unit.
+.It Xo
+.Fn dwarf_next_cu_header ,
+.Fn dwarf_next_cu_header_b ,
+.Fn dwarf_next_cu_header_c
+.Xc
+Step through compilation units in a debug context.
+.El
+.It Debugging Information Entries
+.Bl -tag -compact
+.It Fn dwarf_child
+Returns the child of a debugging information entry.
+.It Fn dwarf_die_abbrev_code
+Returns the abbreviation code for a debugging information entry.
+.It Fn dwarf_die_CU_offset , Fn dwarf_die_CU_offset_range
+Retrieve offsets and lengths for a compilation unit.
+.It Fn dwarf_diename
+Returns the
+.Dv DW_AT_name
+attribute for a debugging information entry.
+.It Fn dwarf_dieoffset
+Retrieves the offset for a debugging information entry.
+.It Fn dwarf_get_die_infotypes_flag
+Indicate the originating section for a debugging information entry.
+.It Fn dwarf_highpc , Fn dwarf_highpc_b
+Return the highest PC value for a debugging information entry.
+.It Fn dwarf_lowpc
+Return the lowest PC value for a debugging information entry.
+.It Fn dwarf_offdie , Fn dwarf_offdie_b
+Retrieve a debugging information entry given an offset.
+.It Fn dwarf_siblingof , Fn dwarf_siblingof_b
+Retrieve the sibling descriptor for a debugging information entry.
+.It Fn dwarf_srclang
+Retrieve the source language attribute for a debugging information
+entry.
+.It Fn dwarf_tag
+Retrieve the tag for a debugging information entry.
+.El
+.It Functions
+.Bl -tag -compact
+.It Fn dwarf_func_cu_offset
+Retrieves the offset for the compilation unit for a function.
+.It Fn dwarf_func_die_offset
+Retrieves the offset for the debugging information entry for a
+function.
+.It Fn dwarf_funcname
+Retrieves the name of a function.
+.It Fn dwarf_func_name_offsets
+Retrieve both the name and offsets for a function.
+.It Fn dwarf_get_funcs
+Retrieve information about static functions.
+.El
+.It Globals
+.Bl -tag -compact
+.It Fn dwarf_get_globals
+Retrieve a list of globals.
+.It Fn dwarf_global_cu_offset
+Return the offset for compilation unit for a global.
+.It Fn dwarf_global_die_offset
+Return the offset for the debugging information entry for a global.
+.It Fn dwarf_global_name_offsets
+Return the name and offsets for a global.
+.It Fn dwarf_globname
+Return the name for a global.
+.El
+.It Initialization and Finalization
+Functions
+.Fn dwarf_elf_init
+and
+.Fn dwarf_init
+may be used for initialization.
+The function
+.Fn dwarf_finish
+may be used to release resources.
+.Pp
+The functions
+.Fn dwarf_object_init
+and
+.Fn dwarf_object_finish
+allow an application to specify alternate low-level file access
+routines.
+.It Line Numbers
+.Bl -tag -compact
+.It Fn dwarf_lineaddr
+Retrieve the program address for a source line.
+.It Fn dwarf_linebeginstatement
+Check if a source line corresponds to the beginning of a statement.
+.It Fn dwarf_lineblock
+Check if a source line corresponds to the start of a basic block.
+.It Fn dwarf_lineendsequence
+Check if the source line corresponds to the end of a sequence of
+instructions.
+.It Fn dwarf_lineno
+Retrieve the line number for a line descriptor.
+.It Fn dwarf_lineoff
+Retrieve the column number for a line descriptor.
+.It Fn dwarf_linesrc
+Retrieve the source file for a line descriptor.
+.It Fn dwarf_line_srcfileno
+Retrieve the index of the source file for a line descriptor.
+.It Fn dwarf_srcfiles
+Retrieve source files for a compilation unit.
+.It Fn dwarf_srclines
+Return line number information for a compilation unit.
+.El
+.It Location Lists
+.Bl -tag -compact
+.It Fn dwarf_get_loclist_entry
+Retrieve a location list entry.
+.It Fn dwarf_loclist , Fn dwarf_loclist_n
+Retrieve location expressions.
+.It Xo
+.Fn dwarf_loclist_from_expr ,
+.Fn dwarf_loclist_from_expr_a ,
+.Fn dwarf_loclist_from_expr_b
+.Xc
+Translate a location expression into a location descriptor.
+.El
+.It Error Handling
+.Bl -tag -compact
+.It Fn dwarf_errmsg
+Retrieve a human-readable error message.
+.It Fn dwarf_errno
+Retrieve an error number from an error descriptor.
+.It Fn dwarf_seterrarg
+Set the argument passed to a callback error handler.
+.It Fn dwarf_seterrhand
+Set the callback handler to be called in case of an error.
+.El
+.It Frame Handling
+.Bl -tag -compact
+.It Fn dwarf_expand_frame_instructions
+Translate frame instruction bytes.
+.It Fn dwarf_set_frame_cfa_value
+Set the CFA parameter for the internal register rule table.
+.It Fn dwarf_set_frame_rule_initial_value
+Set the initial value of the register rules in the internal register
+rule table.
+.It Fn dwarf_set_frame_rule_table_size
+Set the maximum number of columns in the register rule table.
+.It Fn dwarf_set_frame_same_value
+Set the register number representing the
+.Dq "same value"
+rule.
+.It Fn dwarf_set_frame_undefined_value
+Set the register number representing the
+.Dq "undefined"
+rule.
+.El
+.It Macros
+.Bl -tag -compact
+.It Fn dwarf_find_macro_value_start
+Return the macro value part of a macro string.
+.It Fn dwarf_get_macro_details
+Retrieve macro information.
+.El
+.It Memory Management
+In the DWARF consumer API, the rules for memory management differ
+between functions.
+In some cases, the memory areas returned to the application by the
+library are freed by calling specific API functions.
+In others, the deallocation function
+.Fn dwarf_dealloc
+suffices.
+The individual manual pages for the API's functions document the
+specific memory management rules to be followed.
+.Pp
+The function
+.Fn dwarf_dealloc
+is used to mark memory arenas as unused.
+Additionally, the following functions release specific types of
+DWARF resources:
+.Fn dwarf_fde_cie_list_dealloc ,
+.Fn dwarf_funcs_dealloc ,
+.Fn dwarf_globals_dealloc ,
+.Fn dwarf_pubtypes_dealloc ,
+.Fn dwarf_ranges_dealloc ,
+.Fn dwarf_srclines_dealloc ,
+.Fn dwarf_types_dealloc ,
+.Fn dwarf_vars_dealloc ,
+and
+.Fn dwarf_weaks_dealloc .
+.It Symbol Constants
+The following functions may be used to return symbolic names
+for DWARF constants:
+.Fn dwarf_get_ACCESS_name ,
+.Fn dwarf_get_AT_name ,
+.Fn dwarf_get_ATE_name ,
+.Fn dwarf_get_CC_name ,
+.Fn dwarf_get_CFA_name ,
+.Fn dwarf_get_CHILDREN_name ,
+.Fn dwarf_get_DS_name ,
+.Fn dwarf_get_DSC_name ,
+.Fn dwarf_get_EH_name ,
+.Fn dwarf_get_END_name ,
+.Fn dwarf_get_FORM_name ,
+.Fn dwarf_get_ID_name ,
+.Fn dwarf_get_INL_name ,
+.Fn dwarf_get_LANG_name ,
+.Fn dwarf_get_LNE_name ,
+.Fn dwarf_get_LNS_name ,
+.Fn dwarf_get_MACINFO_name ,
+.Fn dwarf_get_OP_name ,
+.Fn dwarf_get_ORD_name ,
+.Fn dwarf_get_TAG_name ,
+.Fn dwarf_get_VIRTUALITY_name ,
+and
+.Fn dwarf_get_VIS_name .
+.It Types
+.Bl -tag -compact
+.It Fn dwarf_get_pubtypes , Fn dwarf_get_types
+Retrieve descriptors for user-defined types.
+.It Fn dwarf_next_types_section
+Step through
+.Dq \&.debug_types
+sections in a debug context.
+.It Fn dwarf_pubtype_cu_offset , Fn dwarf_type_cu_offset
+Return the offset for the compilation unit for a type.
+.It Fn dwarf_pubtype_die_offset , Fn dwarf_type_die_offset
+Return the offset for the debugging information entry for a type.
+.It Fn dwarf_pubtypename , Fn dwarf_typename
+Retrieve the name of a type.
+.It Fn dwarf_pubtype_name_offsets , Fn dwarf_type_name_offsets
+Retrieve the name and offsets for a type.
+.El
+.It Variables
+.Bl -tag -compact
+.It Fn dwarf_get_vars
+Retrieve descriptors for static variables.
+.It Fn dwarf_var_cu_offset
+Return the offset for the compilation unit for a variable.
+.It Fn dwarf_var_die_offset
+Return the offset for the debugging information entry for a variable.
+.It Fn dwarf_varname
+Retrieve the name of a variable.
+.It Fn dwarf_var_name_offsets
+Retrieve the name and offsets for a variable.
+.El
+.It Weak Symbols
+.Bl -tag -compact
+.It Fn dwarf_get_weaks
+Retrieve information about weak symbols.
+.It Fn dwarf_weak_cu_offset
+Return the offset for the compilation unit for a weak symbol.
+.It Fn dwarf_weak_die_offset
+Return the offset for the debugging information entry for a weak symbol.
+.It Fn dwarf_weakname
+Retrieve the name of a weak symbol.
+.It Fn dwarf_weak_name_offsets
+Retrieve the name and offsets for a weak symbol.
+.El
+.It Miscellaneous
+.Bl -tag -compact
+.It Fn dwarf_get_elf
+Retrieve the ELF descriptor for a debug context, see
+.Xr elf 3 .
+.It Fn dwarf_get_str
+Retrieve a NUL-terminated string from the DWARF string section.
+.It Fn dwarf_set_reloc_application
+Control whether relocations are to be handled by
+.Lb libdwarf .
+.El
+.El
+.Sh The DWARF Producer API
+The DWARF producer API permits applications to add DWARF information to
+an object file.
+.Pp
+The major functional groups of functions in the producer API are listed
+below.
+.Bl -tag -width "CCCC"
+.It Attribute Management
+The following functions are used to attach attributes to a debugging
+information entry:
+.Fn dwarf_add_AT_comp_dir ,
+.Fn dwarf_add_AT_const_value_signedint ,
+.Fn dwarf_add_AT_const_value_string ,
+.Fn dwarf_add_AT_const_value_unsignedint ,
+.Fn dwarf_add_AT_dataref ,
+.Fn dwarf_add_AT_flag ,
+.Fn dwarf_add_AT_location_expr ,
+.Fn dwarf_add_AT_name ,
+.Fn dwarf_add_AT_producer ,
+.Fn dwarf_add_AT_ref_address ,
+.Fn dwarf_add_AT_reference ,
+.Fn dwarf_add_AT_signed_const ,
+.Fn dwarf_add_AT_string ,
+.Fn dwarf_add_AT_targ_address ,
+.Fn dwarf_add_AT_targ_address_b
+and
+.Fn dwarf_add_AT_unsigned_const .
+.It Debugging Information Entry Management
+.Bl -tag -compact
+.It Fn dwarf_add_die_to_debug
+Set the root debugging information entry for a DWARF producer instance.
+.It Fn dwarf_die_link
+Links debugging information entries.
+.It Fn dwarf_new_die
+Allocate a new debugging information entry.
+.El
+.It Initialization and Finalization
+The functions
+.Fn dwarf_producer_init
+and
+.Fn dwarf_producer_init_b
+are used to initialize a producer instance.
+.Pp
+When done, applications release resources using the function
+.Fn dwarf_producer_finish .
+.It Relocations and Sections
+.Bl -tag -compact
+.It Fn dwarf_get_relocation_info
+Retrieve a relocation array from a producer instance.
+.It Fn dwarf_get_relocation_info_count
+Return the number of relocation arrays for a producer instance.
+.It Fn dwarf_get_section_bytes
+Retrieve the ELF byte stream for a section.
+.It Fn dwarf_reset_section_bytes
+Reset internal state for a producer instance.
+.It Fn dwarf_transform_to_disk_form
+Prepare byte streams for writing out.
+.El
+.It Macros
+.Bl -tag -compact
+.It Fn dwarf_def_macro
+Add a macro definition.
+.It Fn dwarf_end_macro_file , Fn dwarf_start_macro_file
+Record macro file related information.
+.It Fn dwarf_undef_macro
+Note the removal of a macro definition.
+.It Fn dwarf_vendor_ext
+Enables storing macro information as specified in the DWARF standard.
+.El
+.It Symbols, Expressions, Addresses and Offsets
+.Bl -tag -compact
+.It Fn dwarf_add_arange , Fn dwarf_add_arange_b
+Add address range information.
+.It Fn dwarf_add_directory_decl
+Add information about an include directory to a producer instance.
+.It Fn dwarf_add_fde_inst
+Add an operation to a frame descriptor entry.
+.It Fn dwarf_add_file_decl
+Add information about a source file to a producer instance.
+.It Fn dwarf_add_frame_cie
+Add call information to a frame descriptor.
+.It Fn dwarf_add_frame_fde , Fn dwarf_add_frame_fde_b
+Link a frame descriptor to a producer instance.
+.It Fn dwarf_add_funcname
+Add information about a function to a producer instance.
+.It Fn dwarf_add_line_entry
+Record mapping information between machine addresses and a source line.
+.It Fn dwarf_add_expr_addr , Fn dwarf_add_expr_addr_b
+Add a
+.Dv DW_OP_addr
+opcode to a location expression.
+.It Fn dwarf_add_expr_gen
+Add an operator to a location expression.
+.It Fn dwarf_add_pubname
+Add information about a global name to a producer instance.
+.It Fn dwarf_add_typename
+Add information about a type to a producer instance.
+.It Fn dwarf_add_varname
+Add information about a static variable to a producer instance.
+.It Fn dwarf_add_weakname
+Add information about a weak symbol to a producer instance.
+.It Fn dwarf_expr_current_offset
+Retrieve the current size of a location expression.
+.It Fn dwarf_expr_into_block
+Convert a location expression into a byte stream.
+.It Fn dwarf_fde_cfa_offset
+Append a
+.Dv DW_CFA_offset
+operation to a frame descriptor.
+.It Fn dwarf_lne_end_sequence , Fn dwarf_lne_set_address
+Note address ranges for source lines.
+.It Fn dwarf_new_expr
+Allocate a location expression descriptor.
+.It Fn dwarf_new_fde
+Allocate a frame descriptor.
+.El
+.It Miscellaneous
+The function
+.Fn dwarf_producer_set_isa
+sets the instruction set architecture for the producer instance.
+.El
+.Sh COMPATIBILITY
+This implementation is believed to be source compatible with the
+SGI/GNU DWARF(3) library, version 20110113.
+.Pp
+Known differences with the SGI/GNU library include:
+.Bl -bullet -compact
+.It
+The memory management scheme used differs, in a backward-compatible
+way.
+See
+.Sx Memory Management
+above, for coding guidelines for portable applications.
+.It
+There is provision for setting a library-wide error handler in
+addition to the per-debug context handlers supported by the SGI/GNU
+API, see the subsection
+.Sx Error Handling
+above.
+.El
+.Ss Extensions
+The following APIs are extensions specific to this implementation:
+.Bl -bullet -compact
+.It
+.Fn dwarf_attroffset
+.It
+.Fn dwarf_next_types_section
+.It
+.Fn dwarf_producer_set_isa
+.El
+.Sh SEE ALSO
+.Xr elf 3
+.Sh STANDARDS
+The DWARF standard is defined by
+.Rs
+.%T "The DWARF Debugging Information Format"
+.%V "Version 4"
+.%O "http://www.dwarfstd.org/"
+.Re
+.Sh HISTORY
+The DWARF(3) API originated at Silicon Graphics Inc.
+.Pp
+A BSD-licensed implementation of a subset of the API was written by
+.An John Birrell Aq Mt jb@FreeBSD.org
+for the FreeBSD project.
+The implementation was subsequently revised and completed by
+.An Kai Wang Aq Mt kaiwang27@users.sourceforge.net .
+.Pp
+Manual pages for this implementation were written by
+.An Joseph Koshy Aq Mt jkoshy@users.sourceforge.net
+and
+.An Kai Wang Aq Mt kaiwang27@users.sourceforge.net .
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf.h	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,652 @@
+/*-
+ * Copyright (c) 2007 John Birrell (jb@freebsd.org)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *notice, this list of conditions and the following disclaimer in the
+ *documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: dwarf.h 3494 2016-09-20 17:16:13Z emaste $
+ */
+
+#ifndef	_DWARF_H_
+#define	_DWARF_H_
+
+#define DW_TAG_array_type		0x01
+#define DW_TAG_class_type		0x02
+#define DW_TAG_entry_point		0x03
+#define DW_TAG_enumeration_type		0x04
+#define DW_TAG_formal_parameter		0x05
+#define DW_TAG_imported_declaration	0x08
+#define DW_TAG_label			0x0a
+#define DW_TAG_lexical_block		0x0b
+#define DW_TAG_member			0x0d
+#define DW_TAG_pointer_type		0x0f
+#define DW_TAG_reference_type		0x10
+#define DW_TAG_compile_unit		0x11
+#define DW_TAG_string_type		0x12
+#define DW_TAG_structure_type		0x13
+#define DW_TAG_subroutine_type		0x15
+#define DW_TAG_typedef			0x16
+#define DW_TAG_union_type		0x17
+#define DW_TAG_unspecified_parameters	0x18
+#define DW_TAG_variant			0x19
+#define DW_TAG_common_block		0x1a
+#define DW_TAG_common_inclusion		0x1b
+#define DW_TAG_inheritance		0x1c
+#define DW_TAG_inlined_subroutine	0x1d
+#define DW_TAG_module			0x1e
+#define DW_TAG_ptr_to_member_type	0x1f
+#define DW_TAG_set_type			0x20
+#define DW_TAG_subrange_type		0x21
+#define DW_TAG_with_stmt		0x22
+#define DW_TAG_access_declaration	0x23
+#define DW_TAG_base_type		0x24
+#define DW_TAG_catch_block		0x25
+#define DW_TAG_const_type		0x26
+#define DW_TAG_constant			0x27
+#define DW_TAG_enumerator		0x28
+#define DW_TAG_friend			0x2a
+#define DW_TAG_namelist			0x2b
+#define DW_TAG_namelist_item		0x2c
+#define DW_TAG_packed_type		0x2d
+#define DW_TAG_subprogram		0x2e
+#define DW_TAG_template_type_parameter	0x2f
+#define DW_TAG_template_type_param	0x2f
+#define DW_TAG_template_value_parameter	0x30
+#define DW_TAG_template_value_param	0x30
+#define DW_TAG_thrown_type		0x31
+#define DW_TAG_try_block		0x32
+#define DW_TAG_variant_part		0x33
+#define DW_TAG_variable			0x34
+#define DW_TAG_volatile_type		0x35
+#define DW_TAG_dwarf_procedure          0x36
+#define DW_TAG_restrict_type            0x37
+#define DW_TAG_interface_type           0x38
+#define DW_TAG_namespace                0x39
+#define DW_TAG_imported_module          0x3a
+#define DW_TAG_unspecified_type         0x3b
+#define DW_TAG_partial_unit             0x3c
+#define DW_TAG_imported_unit            0x3d
+#define DW_TAG_condition                0x3f
+#define DW_TAG_shared_type              0x40
+#define DW_TAG_type_unit		0x41
+#define DW_TAG_rvalue_reference_type	0x42
+#define DW_TAG_template_alias		0x43
+#define DW_TAG_lo_user			0x4080
+#define DW_TAG_hi_user			0xffff
+
+/* GNU extensions. */
+#define	DW_TAG_format_label		0x4101
+#define	DW_TAG_function_template	0x4102
+#define	DW_TAG_class_template		0x4103
+#define	DW_TAG_GNU_BINCL		0x4104
+#define	DW_TAG_GNU_EINCL		0x4105
+#define	DW_TAG_GNU_template_template_parameter	0x4106
+#define	DW_TAG_GNU_template_template_param	0x4106
+#define	DW_TAG_GNU_template_parameter_pack	0x4107
+#define	DW_TAG_GNU_formal_parameter_pack	0x4108
+#define	DW_TAG_GNU_call_site			0x4109
+#define	DW_TAG_GNU_call_site_parameter		0x410a
+
+#define DW_CHILDREN_no			0x00
+#define DW_CHILDREN_yes			0x01
+
+#define DW_AT_sibling			0x01
+#define DW_AT_location			0x02
+#define DW_AT_name			0x03
+#define DW_AT_ordering			0x09
+#define DW_AT_subscr_data		0x0a
+#define DW_AT_byte_size			0x0b
+#define DW_AT_bit_offset		0x0c
+#define DW_AT_bit_size			0x0d
+#define DW_AT_element_list		0x0f
+#define DW_AT_stmt_list			0x10
+#define DW_AT_low_pc			0x11
+#define DW_AT_high_pc			0x12
+#define DW_AT_language			0x13
+#define DW_AT_member			0x14
+#define DW_AT_discr			0x15
+#define DW_AT_discr_value		0x16
+#define DW_AT_visibility		0x17
+#define DW_AT_import			0x18
+#define DW_AT_string_length		0x19
+#define DW_AT_common_reference		0x1a
+#define DW_AT_comp_dir			0x1b
+#define DW_AT_const_value		0x1c
+#define DW_AT_containing_type		0x1d
+#define DW_AT_default_value		0x1e
+#define DW_AT_inline			0x20
+#define DW_AT_is_optional		0x21
+#define DW_AT_lower_bound		0x22
+#define DW_AT_producer			0x25
+#define DW_AT_prototyped		0x27
+#define DW_AT_return_addr		0x2a
+#define DW_AT_start_scope		0x2c
+#define DW_AT_bit_stride		0x2e
+#define DW_AT_stride_size		0x2e
+#define DW_AT_upper_bound		0x2f
+#define DW_AT_abstract_origin		0x31
+#define DW_AT_accessibility		0x32
+#define DW_AT_address_class		0x33
+#define DW_AT_artificial		0x34
+#define DW_AT_base_types		0x35
+#define DW_AT_calling_convention	0x36
+#define DW_AT_count			0x37
+#define DW_AT_data_member_location	0x38
+#define DW_AT_decl_column		0x39
+#define DW_AT_decl_file			0x3a
+#define DW_AT_decl_line			0x3b
+#define DW_AT_declaration		0x3c
+#define DW_AT_discr_list		0x3d
+#define DW_AT_encoding			0x3e
+#define DW_AT_external			0x3f
+#define DW_AT_frame_base		0x40
+#define DW_AT_friend			0x41
+#define DW_AT_identifier_case		0x42
+#define DW_AT_macro_info		0x43
+#define DW_AT_namelist_item		0x44
+#define DW_AT_priority			0x45
+#define DW_AT_segment			0x46
+#define DW_AT_specification		0x47
+#define DW_AT_static_link		0x48
+#define DW_AT_type			0x49
+#define DW_AT_use_location		0x4a
+#define DW_AT_variable_parameter	0x4b
+#define DW_AT_virtuality		0x4c
+#define DW_AT_vtable_elem_location	0x4d
+#define DW_AT_allocated			0x4e
+#define DW_AT_associated		0x4f
+#define DW_AT_data_location		0x50
+#define DW_AT_byte_stride		0x51
+#define DW_AT_entry_pc			0x52
+#define DW_AT_use_UTF8			0x53
+#define DW_AT_extension			0x54
+#define DW_AT_ranges			0x55
+#define DW_AT_trampoline		0x56
+#define DW_AT_call_column		0x57
+#define DW_AT_call_file			0x58
+#define DW_AT_call_line			0x59
+#define DW_AT_description		0x5a
+#define DW_AT_binary_scale		0x5b
+#define DW_AT_decimal_scale		0x5c
+#define DW_AT_small			0x5d
+#define DW_AT_decimal_sign		0x5e
+#define DW_AT_digit_count		0x5f
+#define DW_AT_picture_string		0x60
+#define DW_AT_mutable			0x61
+#define DW_AT_threads_scaled		0x62
+#define DW_AT_explicit			0x63
+#define DW_AT_object_pointer		0x64
+#define DW_AT_endianity			0x65
+#define DW_AT_elemental			0x66
+#define DW_AT_pure			0x67
+#define DW_AT_recursive			0x68
+#define DW_AT_signature			0x69
+#define DW_AT_main_subprogram		0x6a
+#define DW_AT_data_bit_offset		0x6b
+#define DW_AT_const_expr		0x6c
+#define DW_AT_enum_class		0x6d
+#define DW_AT_linkage_name		0x6e
+#define DW_AT_lo_user			0x2000
+#define DW_AT_hi_user			0x3fff
+
+/* SGI/MIPS extensions. */
+#define DW_AT_MIPS_fde				0x2001
+#define DW_AT_MIPS_loop_begin			0x2002
+#define DW_AT_MIPS_tail_loop_begin		0x2003
+#define DW_AT_MIPS_epilog_begin			0x2004
+#define DW_AT_MIPS_loop_unroll_factor		0x2005
+#define DW_AT_MIPS_software_pipeline_depth	0x2006
+#define DW_AT_MIPS_linkage_name			0x2007
+#define DW_AT_MIPS_stride			0x2008
+#define DW_AT_MIPS_abstract_name		0x2009
+#define DW_AT_MIPS_clone_origin			0x200a
+#define DW_AT_MIPS_has_inlines			0x200b
+#define DW_AT_MIPS_stride_byte			0x200c
+#define DW_AT_MIPS_stride_elem			0x200d
+#define DW_AT_MIPS_ptr_dopetype			0x200e
+#define DW_AT_MIPS_allocatable_dopetype		0x200f
+#define DW_AT_MIPS_assumed_shape_dopetype	0x2010
+#define DW_AT_MIPS_assumed_size			0x2011
+
+/* GNU extensions. */
+#define	DW_AT_sf_names				0x2101
+#define	DW_AT_src_info				0x2102
+#define	DW_AT_mac_info				0x2103
+#define	DW_AT_src_coords			0x2104
+#define	DW_AT_body_begin			0x2105
+#define	DW_AT_body_end				0x2106
+#define	DW_AT_GNU_vector			0x2107
+#define	DW_AT_GNU_guarded_by			0x2108
+#define	DW_AT_GNU_pt_guarded_by			0x2109
+#define	DW_AT_GNU_guarded			0x210a
+#define	DW_AT_GNU_pt_guarded			0x210b
+#define	DW_AT_GNU_locks_excluded		0x210c
+#define	DW_AT_GNU_exclusive_locks_required	0x210d
+#define	DW_AT_GNU_shared_locks_required		0x210e
+#define	DW_AT_GNU_odr_signature			0x210f
+#define	DW_AT_GNU_template_name			0x2110
+#define	DW_AT_GNU_call_site_value		0x2111
+#define	DW_AT_GNU_call_site_data_value		0x2112
+#define	DW_AT_GNU_call_site_target		0x2113
+#define	DW_AT_GNU_call_site_target_clobbered	0x2114
+#define	DW_AT_GNU_tail_call			0x2115
+#define	DW_AT_GNU_all_tail_call_sites		0x2116
+#define	DW_AT_GNU_all_call_sites		0x2117
+#define	DW_AT_GNU_all_source_call_sites		0x2118
+
+/* Apple extensions. */
+#define	DW_AT_APPLE_optimized			0x3fe1
+#define	DW_AT_APPLE_flags			0x3fe2
+#define	DW_AT_APPLE_isa				0x3fe3
+#define	DW_AT_APPLE_block			0x3fe4
+#define	DW_AT_APPLE_major_runtime_vers		0x3fe5
+#define	DW_AT_APPLE_runtime_class		0x3fe6
+#define	DW_AT_APPLE_omit_frame_ptr		0x3fe7
+#define	DW_AT_APPLE_property_name		0x3fe8
+#define	DW_AT_APPLE_property_getter		0x3fe9
+#define	DW_AT_APPLE_property_setter		0x3fea
+#define	DW_AT_APPLE_property_attribute		0x3feb
+#define	DW_AT_APPLE_objc_complete_type		0x3fec
+#define	DW_AT_APPLE_property			0x3fed
+
+#define DW_FORM_addr			0x01
+#define DW_FORM_block2			0x03
+#define DW_FORM_block4			0x04
+#define DW_FORM_data2			0x05
+#define DW_FORM_data4			0x06
+#define DW_FORM_data8			0x07
+#define DW_FORM_string			0x08
+#define DW_FORM_block			0x09
+#define DW_FORM_block1			0x0a
+#define DW_FORM_data1			0x0b
+#define DW_FORM_flag			0x0c
+#define DW_FORM_sdata			0x0d
+#define DW_FORM_strp			0x0e
+#define DW_FORM_udata			0x0f
+#define DW_FORM_ref_addr		0x10
+#define DW_FORM_ref1			0x11
+#define DW_FORM_ref2			0x12
+#define DW_FORM_ref4			0x13
+#define DW_FORM_ref8			0x14
+#define DW_FORM_ref_udata		0x15
+#define DW_FORM_indirect		0x16
+#define DW_FORM_sec_offset		0x17
+#define DW_FORM_exprloc			0x18
+#define DW_FORM_flag_present		0x19
+#define DW_FORM_ref_sig8		0x20
+#define	DW_FORM_GNU_ref_alt		0x1f20
+#define	DW_FORM_GNU_strp_alt		0x1f21
+
+#define DW_OP_addr			0x03
+#define DW_OP_deref			0x06
+#define DW_OP_const1u			0x08
+#define DW_OP_const1s			0x09
+#define DW_OP_const2u			0x0a
+#define DW_OP_const2s			0x0b
+#define DW_OP_const4u			0x0c
+#define DW_OP_const4s			0x0d
+#define DW_OP_const8u			0x0e
+#define DW_OP_const8s			0x0f
+#define DW_OP_constu			0x10
+#define DW_OP_consts			0x11
+#define DW_OP_dup			0x12
+#define DW_OP_drop			0x13
+#define DW_OP_over			0x14
+#define DW_OP_pick			0x15
+#define DW_OP_swap			0x16
+#define DW_OP_rot			0x17
+#define DW_OP_xderef			0x18
+#define DW_OP_abs			0x19
+#define DW_OP_and			0x1a
+#define DW_OP_div			0x1b
+#define DW_OP_minus			0x1c
+#define DW_OP_mod			0x1d
+#define DW_OP_mul			0x1e
+#define DW_OP_neg			0x1f
+#define DW_OP_not			0x20
+#define DW_OP_or			0x21
+#define DW_OP_plus			0x22
+#define DW_OP_plus_uconst		0x23
+#define DW_OP_shl			0x24
+#define DW_OP_shr			0x25
+#define DW_OP_shra			0x26
+#define DW_OP_xor			0x27
+#define DW_OP_bra			0x28
+#define DW_OP_eq			0x29
+#define DW_OP_ge			0x2a
+#define DW_OP_gt			0x2b
+#define DW_OP_le			0x2c
+#define DW_OP_lt			0x2d
+#define DW_OP_ne			0x2e
+#define DW_OP_skip			0x2f
+#define DW_OP_lit0			0x30
+#define DW_OP_lit1			0x31
+#define DW_OP_lit2			0x32
+#define DW_OP_lit3			0x33
+#define DW_OP_lit4			0x34
+#define DW_OP_lit5			0x35
+#define DW_OP_lit6			0x36
+#define DW_OP_lit7			0x37
+#define DW_OP_lit8			0x38
+#define DW_OP_lit9			0x39
+#define DW_OP_lit10			0x3a
+#define DW_OP_lit11			0x3b
+#define DW_OP_lit12			0x3c
+#define DW_OP_lit13			0x3d
+#define DW_OP_lit14			0x3e
+#define DW_OP_lit15			0x3f
+#define DW_OP_lit16			0x40
+#define DW_OP_lit17			0x41
+#define DW_OP_lit18			0x42
+#define DW_OP_lit19			0x43
+#define DW_OP_lit20			0x44
+#define DW_OP_lit21			0x45
+#define DW_OP_lit22			0x46
+#define DW_OP_lit23			0x47
+#define DW_OP_lit24			0x48
+#define DW_OP_lit25			0x49
+#define DW_OP_lit26			0x4a
+#define DW_OP_lit27			0x4b
+#define DW_OP_lit28			0x4c
+#define DW_OP_lit29			0x4d
+#define DW_OP_lit30			0x4e
+#define DW_OP_lit31			0x4f
+#define DW_OP_reg0			0x50
+#define DW_OP_reg1			0x51
+#define DW_OP_reg2			0x52
+#define DW_OP_reg3			0x53
+#define DW_OP_reg4			0x54
+#define DW_OP_reg5			0x55
+#define DW_OP_reg6			0x56
+#define DW_OP_reg7			0x57
+#define DW_OP_reg8			0x58
+#define DW_OP_reg9			0x59
+#define DW_OP_reg10			0x5a
+#define DW_OP_reg11			0x5b
+#define DW_OP_reg12			0x5c
+#define DW_OP_reg13			0x5d
+#define DW_OP_reg14			0x5e
+#define DW_OP_reg15			0x5f
+#define DW_OP_reg16			0x60
+#define DW_OP_reg17			0x61
+#define DW_OP_reg18			0x62
+#define DW_OP_reg19			0x63
+#define DW_OP_reg20			0x64
+#define DW_OP_reg21			0x65
+#define DW_OP_reg22			0x66
+#define DW_OP_reg23			0x67
+#define DW_OP_reg24			0x68
+#define DW_OP_reg25			0x69
+#define DW_OP_reg26			0x6a
+#define DW_OP_reg27			0x6b
+#define DW_OP_reg28			0x6c
+#define DW_OP_reg29			0x6d
+#define DW_OP_reg30			0x6e
+#define DW_OP_reg31			0x6f
+#define DW_OP_breg0			0x70
+#define DW_OP_breg1			0x71
+#define DW_OP_breg2			0x72
+#define DW_OP_breg3			0x73
+#define DW_OP_breg4			0x74
+#define DW_OP_breg5			0x75
+#define DW_OP_breg6			0x76
+#define DW_OP_breg7			0x77
+#define DW_OP_breg8			0x78
+#define DW_OP_breg9			0x79
+#define DW_OP_breg10			0x7a
+#define DW_OP_breg11			0x7b
+#define DW_OP_breg12			0x7c
+#define DW_OP_breg13			0x7d
+#define DW_OP_breg14			0x7e
+#define DW_OP_breg15			0x7f
+#define DW_OP_breg16			0x80
+#define DW_OP_breg17			0x81
+#define DW_OP_breg18			0x82
+#define DW_OP_breg19			0x83
+#define DW_OP_breg20			0x84
+#define DW_OP_breg21			0x85
+#define DW_OP_breg22			0x86
+#define DW_OP_breg23			0x87
+#define DW_OP_breg24			0x88
+#define DW_OP_breg25			0x89
+#define DW_OP_breg26			0x8a
+#define DW_OP_breg27			0x8b
+#define DW_OP_breg28			0x8c
+#define DW_OP_breg29			0x8d
+#define DW_OP_breg30			0x8e
+#define DW_OP_breg31			0x8f
+#define DW_OP_regx			0x90
+#define DW_OP_fbreg			0x91
+#define DW_OP_bregx			0x92
+#define DW_OP_piece			0x93
+#define DW_OP_deref_size		0x94
+#define DW_OP_xderef_size		0x95
+#define DW_OP_nop			0x96
+#define DW_OP_push_object_address	0x97
+#define DW_OP_call2			0x98
+#define DW_OP_call4			0x99
+#define DW_OP_call_ref			0x9a
+#define DW_OP_form_tls_address		0x9b
+#define DW_OP_call_frame_cfa		0x9c
+#define DW_OP_bit_piece			0x9d
+#define DW_OP_implicit_value		0x9e
+#define DW_OP_stack_value		0x9f
+#define DW_OP_lo_user		 	0xe0
+#define DW_OP_hi_user		 	0xff
+
+/* GNU extensions. */
+#define	DW_OP_GNU_push_tls_address	0xe0
+#define	DW_OP_GNU_uninit		0xf0
+#define	DW_OP_GNU_encoded_addr		0xf1
+#define	DW_OP_GNU_implicit_pointer	0xf2
+#define	DW_OP_GNU_entry_value		0xf3
+#define	DW_OP_GNU_const_type		0xf4
+#define	DW_OP_GNU_regval_type		0xf5
+#define	DW_OP_GNU_deref_type		0xf6
+#define	DW_OP_GNU_convert		0xf7
+#define	DW_OP_GNU_reinterpret		0xf9
+#define	DW_OP_GNU_parameter_ref		0xfa
+#define	DW_OP_GNU_addr_index		0xfb
+#define	DW_OP_GNU_const_index		0xfc
+
+#define DW_ATE_address		 	0x1
+#define DW_ATE_boolean		 	0x2
+#define DW_ATE_complex_float	 	0x3
+#define DW_ATE_float		 	0x4
+#define DW_ATE_signed		 	0x5
+#define DW_ATE_signed_char	 	0x6
+#define DW_ATE_unsigned		 	0x7
+#define DW_ATE_unsigned_char	 	0x8
+#define DW_ATE_imaginary_float	 	0x9
+#define DW_ATE_packed_decimal	 	0xa
+#define DW_ATE_numeric_string	 	0xb
+#define DW_ATE_edited		 	0xc
+#define DW_ATE_signed_fixed	 	0xd
+#define DW_ATE_unsigned_fixed	 	0xe
+#define DW_ATE_decimal_float	 	0xf
+#define DW_ATE_lo_user		 	0x80
+#define DW_ATE_hi_user		 	0xff
+
+#define DW_ACCESS_public		0x01
+#define DW_ACCESS_protected	 	0x02
+#define DW_ACCESS_private	 	0x03
+
+#define	DW_END_default			0x00
+#define	DW_END_big			0x01
+#define	DW_END_little			0x02
+#define	DW_END_lo_user			0x40
+#define	DW_END_high_user		0xff
+
+#define DW_VIS_local		 	0x01
+#define DW_VIS_exported		 	0x02
+#define DW_VIS_qualified		0x03
+
+#define DW_VIRTUALITY_none	 	0x00
+#define DW_VIRTUALITY_virtual	 	0x01
+#define DW_VIRTUALITY_pure_virtual 	0x02
+
+#define DW_LANG_C89		 	0x0001
+#define DW_LANG_C		 	0x0002
+#define DW_LANG_Ada83		 	0x0003
+#define DW_LANG_C_plus_plus	 	0x0004
+#define DW_LANG_Cobol74		 	0x0005
+#define DW_LANG_Cobol85		 	0x0006
+#define DW_LANG_Fortran77	 	0x0007
+#define DW_LANG_Fortran90	 	0x0008
+#define DW_LANG_Pascal83		0x0009
+#define DW_LANG_Modula2		 	0x000a
+#define DW_LANG_Java		 	0x000b
+#define DW_LANG_C99		 	0x000c
+#define DW_LANG_Ada95		 	0x000d
+#define DW_LANG_Fortran95	 	0x000e
+#define DW_LANG_PLI		 	0x000f
+#define DW_LANG_ObjC		 	0x0010
+#define DW_LANG_ObjC_plus_plus	 	0x0011
+#define DW_LANG_UPC		 	0x0012
+#define DW_LANG_D		 	0x0013
+#define DW_LANG_Python			0x0014
+#define DW_LANG_OpenCL			0x0015
+#define DW_LANG_Go			0x0016
+#define DW_LANG_Modula3			0x0017
+#define DW_LANG_Haskell			0x0018
+#define DW_LANG_C_plus_plus_03		0x0019
+#define DW_LANG_C_plus_plus_11		0x001a
+#define DW_LANG_OCaml			0x001b
+#define DW_LANG_Rust			0x001c
+#define DW_LANG_C11			0x001d
+#define DW_LANG_Swift			0x001e
+#define DW_LANG_Julia			0x001f
+#define DW_LANG_Dylan			0x0020
+#define DW_LANG_C_plus_plus_14		0x0021
+#define DW_LANG_Fortran03		0x0022
+#define DW_LANG_Fortran08		0x0023
+#define DW_LANG_RenderScript		0x0024
+#define DW_LANG_BLISS			0x0025
+#define DW_LANG_lo_user		 	0x8000
+#define DW_LANG_Mips_Assembler		0x8001
+#define DW_LANG_hi_user		 	0xffff
+
+#define DW_ID_case_sensitive	 	0x00
+#define DW_ID_up_case		 	0x01
+#define DW_ID_down_case		 	0x02
+#define DW_ID_case_insensitive	 	0x03
+
+#define DW_CC_normal		 	0x01
+#define DW_CC_program		 	0x02
+#define DW_CC_nocall		 	0x03
+#define DW_CC_lo_user		 	0x40
+#define DW_CC_hi_user		 	0xff
+
+#define DW_INL_not_inlined	 	0x00
+#define DW_INL_inlined		 	0x01
+#define DW_INL_declared_not_inlined 	0x02
+#define DW_INL_declared_inlined	 	0x03
+
+#define DW_ORD_row_major		0x00
+#define DW_ORD_col_major		0x01
+
+#define	DW_DS_unsigned			0x01
+#define	DW_DS_leading_overpunch		0x02
+#define	DW_DS_trailing_overpunch	0x03
+#define	DW_DS_leading_separate		0x04
+#define	DW_DS_trailing_separate		0x05
+
+#define DW_DSC_label		 	0x00
+#define DW_DSC_range		 	0x01
+
+#define DW_LNS_copy		 	0x01
+#define DW_LNS_advance_pc	 	0x02
+#define DW_LNS_advance_line	 	0x03
+#define DW_LNS_set_file		 	0x04
+#define DW_LNS_set_column	 	0x05
+#define DW_LNS_negate_stmt	 	0x06
+#define DW_LNS_set_basic_block	 	0x07
+#define DW_LNS_const_add_pc	 	0x08
+#define DW_LNS_fixed_advance_pc	 	0x09
+#define DW_LNS_set_prologue_end	 	0x0a
+#define DW_LNS_set_epilogue_begin 	0x0b
+#define DW_LNS_set_isa		 	0x0c
+
+#define DW_LNE_end_sequence	 	0x01
+#define DW_LNE_set_address	 	0x02
+#define DW_LNE_define_file	 	0x03
+#define DW_LNE_lo_user		 	0x80
+#define DW_LNE_hi_user		 	0xff
+
+#define DW_MACINFO_define	 	0x01
+#define DW_MACINFO_undef		0x02
+#define DW_MACINFO_start_file	 	0x03
+#define DW_MACINFO_end_file	 	0x04
+#define DW_MACINFO_vendor_ext	 	0xff
+
+#define DW_CFA_advance_loc		0x40
+#define DW_CFA_offset	 		0x80
+#define DW_CFA_restore	 		0xc0
+#define DW_CFA_extended			0
+
+#define DW_CFA_nop	 		0x00
+#define DW_CFA_set_loc	 		0x01
+#define DW_CFA_advance_loc1 		0x02
+#define DW_CFA_advance_loc2 		0x03
+#define DW_CFA_advance_loc4 		0x04
+#define DW_CFA_offset_extended 		0x05
+#define DW_CFA_restore_extended 	0x06
+#define DW_CFA_undefined		0x07
+#define DW_CFA_same_value 		0x08
+#define DW_CFA_register	 		0x09
+#define DW_CFA_remember_state 		0x0a
+#define DW_CFA_restore_state 		0x0b
+#define DW_CFA_def_cfa	 		0x0c
+#define DW_CFA_def_cfa_register 	0x0d
+#define DW_CFA_def_cfa_offset 		0x0e
+#define DW_CFA_def_cfa_expression 	0x0f
+#define DW_CFA_expression 		0x10
+#define DW_CFA_offset_extended_sf 	0x11
+#define DW_CFA_def_cfa_sf 		0x12
+#define DW_CFA_def_cfa_offset_sf 	0x13
+#define DW_CFA_val_offset		0x14
+#define DW_CFA_val_offset_sf 		0x15
+#define DW_CFA_val_expression 		0x16
+#define DW_CFA_lo_user	 		0x1c
+#define DW_CFA_high_user	 	0x3f
+
+/*
+ * LSB(Linux Standard Base) extension to DWARF2.
+ */
+
+#define	DW_EH_PE_absptr			0x00
+#define	DW_EH_PE_uleb128		0x01
+#define	DW_EH_PE_udata2			0x02
+#define	DW_EH_PE_udata4			0x03
+#define	DW_EH_PE_udata8			0x04
+#define	DW_EH_PE_sleb128		0x09
+#define	DW_EH_PE_sdata2			0x0a
+#define	DW_EH_PE_sdata4			0x0b
+#define	DW_EH_PE_sdata8			0x0c
+#define	DW_EH_PE_pcrel			0x10
+#define	DW_EH_PE_textrel		0x20
+#define	DW_EH_PE_datarel		0x30
+#define	DW_EH_PE_funcrel		0x40
+#define	DW_EH_PE_aligned		0x50
+#define	DW_EH_PE_omit			0xff
+
+#endif /* !_DWARF_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_abbrev.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,136 @@
+/*-
+ * Copyright (c) 2009,2011 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_abbrev.c 2072 2011-10-27 03:26:49Z jkoshy $");
+
+int
+dwarf_get_abbrev(Dwarf_Debug dbg, Dwarf_Unsigned offset,
+    Dwarf_Abbrev *return_abbrev, Dwarf_Unsigned *length,
+    Dwarf_Unsigned *attr_count, Dwarf_Error *error)
+{
+	Dwarf_Abbrev ab;
+	int ret;
+
+	if (dbg == NULL || return_abbrev == NULL || length == NULL ||
+	    attr_count == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	ret = _dwarf_abbrev_parse(dbg, NULL, &offset, &ab, error);
+	if (ret != DW_DLE_NONE) {
+		if (ret == DW_DLE_NO_ENTRY) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+			return (DW_DLV_NO_ENTRY);
+		} else
+			return (DW_DLV_ERROR);
+	}
+
+	*return_abbrev = ab;
+	*length = ab->ab_length;
+	*attr_count = ab->ab_atnum;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_abbrev_tag(Dwarf_Abbrev abbrev, Dwarf_Half *return_tag,
+    Dwarf_Error *error)
+{
+
+	if (abbrev == NULL || return_tag == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*return_tag = (Dwarf_Half) abbrev->ab_tag;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_abbrev_code(Dwarf_Abbrev abbrev, Dwarf_Unsigned *return_code,
+    Dwarf_Error *error)
+{
+
+	if (abbrev == NULL || return_code == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*return_code = abbrev->ab_entry;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_abbrev_children_flag(Dwarf_Abbrev abbrev, Dwarf_Signed *return_flag,
+    Dwarf_Error *error)
+{
+
+	if (abbrev == NULL || return_flag == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*return_flag = (Dwarf_Signed) abbrev->ab_children;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_abbrev_entry(Dwarf_Abbrev abbrev, Dwarf_Signed ndx,
+    Dwarf_Half *attr_num, Dwarf_Signed *form, Dwarf_Off *offset,
+    Dwarf_Error *error)
+{
+	Dwarf_AttrDef ad;
+	int i;
+
+	if (abbrev == NULL || attr_num == NULL || form == NULL ||
+	    offset == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (ndx < 0 || (uint64_t) ndx >= abbrev->ab_atnum) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	ad = STAILQ_FIRST(&abbrev->ab_attrdef);
+	for (i = 0; i < ndx && ad != NULL; i++)
+		ad = STAILQ_NEXT(ad, ad_next);
+
+	assert(ad != NULL);
+
+	*attr_num = ad->ad_attrib;
+	*form = ad->ad_form;
+	*offset = ad->ad_offset;
+
+	return (DW_DLV_OK);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_AT_comp_dir.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,99 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_AT_comp_dir.3 2072 2011-10-27 03:26:49Z jkoshy $
+.\"
+.Dd September 4, 2011
+.Os
+.Dt DWARF_ADD_AT_COMP_DIR 3
+.Sh NAME
+.Nm dwarf_add_AT_comp_dir
+.Nd create and attach a DW_AT_comp_dir attribute
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft Dwarf_P_Attribute
+.Fo dwarf_add_AT_comp_dir
+.Fa "Dwarf_P_Die die"
+.Fa "char *dir"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_add_AT_comp_dir
+creates a
+.Dv DW_AT_comp_dir
+attribute descriptor and attaches it to the debugging information
+entry referenced by argument
+.Ar die .
+The created attribute will have DWARF form
+.Dv DW_FORM_strp .
+.Pp
+Argument
+.Ar die
+should reference a debugging information entry allocated using
+.Xr dwarf_new_die 3 .
+.Pp
+Argument
+.Ar dir
+should point to a NUL-terminated string which will become the value of
+the created attribute.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_add_AT_comp_dir
+returns the created attribute descriptor.
+In case of an error, function
+.Fn dwarf_add_AT_comp_dir
+returns
+.Dv DW_DLV_BADADDR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_add_AT_comp_dir
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Either of the arguments
+.Ar die
+or
+.Ar dir
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_AT_const_value_string 3 ,
+.Xr dwarf_add_AT_name 3 ,
+.Xr dwarf_add_AT_producer 3 ,
+.Xr dwarf_add_AT_string 3 ,
+.Xr dwarf_new_die 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_AT_const_value_string.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,126 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_AT_const_value_string.3 2072 2011-10-27 03:26:49Z jkoshy $
+.\"
+.Dd September 4, 2011
+.Os
+.Dt DWARF_ADD_AT_CONST_VALUE_STRING 3
+.Sh NAME
+.Nm dwarf_add_AT_const_value_signedint ,
+.Nm dwarf_add_AT_const_value_string ,
+.Nm dwarf_add_AT_const_value_unsignedint
+.Nd create and attach a DW_AT_const_value attribute
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft Dwarf_P_Attribute
+.Fo dwarf_add_AT_const_value_signedint
+.Fa "Dwarf_P_Die die"
+.Fa "Dwarf_Signed value"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft Dwarf_P_Attribute
+.Fo dwarf_add_AT_const_value_string
+.Fa "Dwarf_P_Die die"
+.Fa "char *str"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft Dwarf_P_Attribute
+.Fo dwarf_add_AT_const_value_unsignedint
+.Fa "Dwarf_P_Die die"
+.Fa "Dwarf_Unsigned value"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+These functions create a
+.Dv DW_AT_const_value
+attribute descriptor and attach it to the debugging information entry
+referenced by argument
+.Ar die .
+.Pp
+Argument
+.Ar die
+should reference a debugging information entry allocated using
+.Xr dwarf_new_die 3 .
+.Pp
+Function
+.Fn dwarf_add_AT_const_value_signedint
+creates a
+.Dv DW_AT_const_value
+attribute descriptor containing the signed value specified by argument
+.Ar value .
+The created attribute descriptor will have DWARF form
+.Dv DW_FORM_sdata .
+.Pp
+Function
+.Fn dwarf_add_AT_const_value_unsignedint
+creates a
+.Dv DW_AT_const_value
+attribute descriptor containing the unsigned value specified by
+argument
+.Ar value .
+The created attribute descriptor will have DWARF form
+.Dv DW_FORM_udata .
+.Pp
+Function
+.Fn dwarf_add_AT_const_value_string
+creates a
+.Dv DW_AT_const_value
+attribute descriptor containing the string pointed to by the
+NUL-terminated argument
+.Ar str .
+The created attribute descriptor will have DWARF form
+.Dv DW_FORM_strp .
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used by these functions to store error
+information in case of an error.
+.Sh RETURN VALUES
+On success, these functions return the created attribute descriptor.
+In case of an error, these functions return
+.Dv DW_DLV_BADADDR
+and set the argument
+.Ar err .
+.Sh ERRORS
+These functions can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Either of the arguments
+.Ar die
+or
+.Ar str
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during execution.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_AT_name 3 ,
+.Xr dwarf_add_AT_signed_const 3 ,
+.Xr dwarf_add_AT_string 3 ,
+.Xr dwarf_add_AT_unsigned_const 3 ,
+.Xr dwarf_new_die 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_AT_dataref.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,122 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_AT_dataref.3 2072 2011-10-27 03:26:49Z jkoshy $
+.\"
+.Dd September 4, 2011
+.Os
+.Dt DWARF_ADD_AT_DATAREF 3
+.Sh NAME
+.Nm dwarf_add_AT_dataref
+.Nd create an attribute descriptor for a relocatable address
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "Dwarf_P_Attribute"
+.Fo dwarf_add_AT_dataref
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_P_Die die"
+.Fa "Dwarf_Half attr"
+.Fa "Dwarf_Unsigned pc_value"
+.Fa "Dwarf_Unsigned sym_index"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_add_AT_dataref
+creates an attribute descriptor for a relocatable address and attaches
+it to the debugging information entry referenced by argument
+.Ar die .
+.Pp
+If flag
+.Dv DW_DLC_SIZE_64
+is set, the address value will be 8 bytes in size and of the DWARF form
+.Dv DW_FORM_data8 .
+Otherwise, the address value will be 4 bytes in size and of the DWARF form
+.Dv DW_FORM_data4 .
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar die
+should reference a debugging information entry allocated using
+.Xr dwarf_new_die 3 .
+.Pp
+Argument
+.Ar attr
+specifies the attribute code of the created attribute descriptor.
+.Pp
+Argument
+.Ar pc_value
+specifies the value of the relocatable address.
+.Pp
+Argument
+.Ar sym_index
+specifies the ELF symbol index of the symbol to be used for
+relocation.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_add_AT_dataref
+returns the created attribute descriptor.
+In case of an error, function
+.Fn dwarf_add_AT_dataref
+returns
+.Dv DW_DLV_BADADDR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_add_AT_dataref
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Either of the arguments
+.Ar dbg
+or
+.Ar die
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_AT_reference 3 ,
+.Xr dwarf_add_AT_ref_address 3 ,
+.Xr dwarf_add_AT_signed_const 3 ,
+.Xr dwarf_add_AT_unsigned_const 3 ,
+.Xr dwarf_new_die 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_AT_flag.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,115 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_AT_flag.3 2072 2011-10-27 03:26:49Z jkoshy $
+.\"
+.Dd September 4, 2011
+.Os
+.Dt DWARF_ADD_AT_FLAG 3
+.Sh NAME
+.Nm dwarf_add_AT_flag
+.Nd create and attach a flag attribute
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft Dwarf_P_Attribute
+.Fo dwarf_add_AT_flag
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_P_Die die"
+.Fa "Dwarf_Half attr"
+.Fa "Dwarf_Small flag"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_add_AT_flag
+creates an attribute descriptor belonging to the
+.Sq flag
+class, and attaches it to the debugging information entry referenced
+by argument
+.Ar die .
+The created attribute descriptor will have DWARF form
+.Dv DW_FORM_flag .
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar die
+should reference a debugging information entry allocated using
+.Xr dwarf_new_die 3 .
+.Pp
+Argument
+.Ar attr
+should specify the attribute code for the new attribute descriptor.
+.Pp
+Argument
+.Ar flag
+should specify the value of the new attribute descriptor.
+A zero value is treated as
+.Sq false
+and a non-zero value as
+.Sq true .
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_add_AT_flag
+returns the created attribute descriptor.
+In case of an error, function
+.Fn dwarf_add_AT_flag
+returns
+.Dv DW_DLV_BADADDR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_add_AT_flag
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Either of the arguments
+.Ar dbg
+or
+.Ar die
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_AT_signed_const 3 ,
+.Xr dwarf_add_AT_unsigned_const 3 ,
+.Xr dwarf_new_die 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_AT_location_expr.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,120 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_AT_location_expr.3 2072 2011-10-27 03:26:49Z jkoshy $
+.\"
+.Dd September 5, 2011
+.Os
+.Dt DWARF_ADD_AT_LOCATION_EXPR 3
+.Sh NAME
+.Nm dwarf_add_AT_location_expr
+.Nd create an attribute descriptor for a location expression
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "Dwarf_P_Attribute"
+.Fo dwarf_add_AT_location_expr
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_P_Die die"
+.Fa "Dwarf_Half attr"
+.Fa "Dwarf_P_Expr loc_expr"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_add_AT_location_expr
+creates an attribute descriptor for a location expression and attaches
+it to the debugging information entry referenced by argument
+.Ar die .
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar die
+should reference a debugging information entry allocated using
+.Xr dwarf_new_die 3 .
+.Pp
+Argument
+.Ar attr
+specifies the attribute code of the created attribute descriptor.
+.Pp
+Argument
+.Ar loc_expr
+should reference a location expression descriptor allocated using
+.Xr dwarf_new_expr 3 .
+.Pp
+The attribute created by function
+.Fn dwarf_add_AT_location_expr
+will have one of the DWARF forms
+.Dv DW_FORM_block ,
+.Dv DW_FORM_block1 ,
+.Dv DW_FORM_block2
+or
+.Dv DW_FORM_block4 ,
+depending on the size of the byte stream generated by the location
+expression descriptor referenced by argument
+.Ar loc_expr .
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used by to store error information in case of
+an error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_add_AT_location_expr
+returns the created attribute descriptor.
+In case of an error, function
+.Fn dwarf_add_AT_location_expr
+returns
+.Dv DW_DLV_BADADDR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_add_AT_location_expr
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar dbg ,
+.Ar die
+or
+.Ar loc_expr
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_new_die 3 ,
+.Xr dwarf_new_expr 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_AT_name.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,99 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_AT_name.3 2072 2011-10-27 03:26:49Z jkoshy $
+.\"
+.Dd September 4, 2011
+.Os
+.Dt DWARF_ADD_AT_NAME 3
+.Sh NAME
+.Nm dwarf_add_AT_name
+.Nd create and attach a DW_AT_name attribute
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft Dwarf_P_Attribute
+.Fo dwarf_add_AT_name
+.Fa "Dwarf_P_Die die"
+.Fa "char *name"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_add_AT_name
+creates a
+.Dv DW_AT_name
+attribute descriptor and attaches it to the debugging information
+entry referenced by argument
+.Ar die .
+The created attribute will have DWARF form
+.Dv DW_FORM_strp .
+.Pp
+Argument
+.Ar die
+should reference a debugging information entry allocated using
+.Xr dwarf_new_die 3 .
+.Pp
+Argument
+.Ar name
+should point to a NUL-terminated string which will become the value of
+the created attribute.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_add_AT_name
+returns the created attribute descriptor.
+In case of an error, function
+.Fn dwarf_add_AT_name
+returns
+.Dv DW_DLV_BADADDR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_add_AT_name
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar die
+or
+.Ar name
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of
+this function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_AT_comp_dir 3 ,
+.Xr dwarf_add_AT_const_value_string 3 ,
+.Xr dwarf_add_AT_producer 3 ,
+.Xr dwarf_add_AT_string 3 ,
+.Xr dwarf_new_die 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_AT_producer.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,99 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_AT_producer.3 2072 2011-10-27 03:26:49Z jkoshy $
+.\"
+.Dd September 4, 2011
+.Os
+.Dt DWARF_ADD_AT_PRODUCER 3
+.Sh NAME
+.Nm dwarf_add_AT_producer
+.Nd create and attach a DW_AT_producer attribute
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft Dwarf_P_Attribute
+.Fo dwarf_add_AT_producer
+.Fa "Dwarf_P_Die die"
+.Fa "char *producer"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_add_AT_producer
+creates a
+.Dv DW_AT_producer
+attribute descriptor and attaches it to the debugging information
+entry referenced by argument
+.Ar die .
+The created attribute will have DWARF form
+.Dv DW_FORM_strp .
+.Pp
+Argument
+.Ar die
+should reference a debugging information entry allocated using
+.Xr dwarf_new_die 3 .
+.Pp
+Argument
+.Ar producer
+should point to a NUL-terminated string which will become the value of
+the created attribute.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_add_AT_producer
+returns the created attribute descriptor.
+In case of an error, function
+.Fn dwarf_add_AT_producer
+returns
+.Dv DW_DLV_BADADDR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_add_AT_producer
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Either of the arguments
+.Ar die
+or
+.Ar producer
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of
+the function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_AT_comp_dir 3 ,
+.Xr dwarf_add_AT_const_value_string 3 ,
+.Xr dwarf_add_AT_name 3 ,
+.Xr dwarf_add_AT_string 3 ,
+.Xr dwarf_new_die 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_AT_ref_address.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,117 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_AT_ref_address.3 2072 2011-10-27 03:26:49Z jkoshy $
+.\"
+.Dd September 7, 2011
+.Os
+.Dt DWARF_ADD_AT_REF_ADDRESS 3
+.Sh NAME
+.Nm dwarf_add_AT_ref_address
+.Nd create a reference class attribute descriptor
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "Dwarf_P_Attribute"
+.Fo dwarf_add_AT_ref_address
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_P_Die die"
+.Fa "Dwarf_Half attr"
+.Fa "Dwarf_Unsigned pc_value"
+.Fa "Dwarf_Unsigned sym_index"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_add_AT_ref_address
+creates a
+.Sq reference
+class attribute descriptor containing a relocatable address value.
+The created attribute will use DWARF form
+.Dv DW_FORM_ref_addr .
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar die
+should reference a debugging information entry allocated using
+.Xr dwarf_new_die 3 .
+.Pp
+Argument
+.Ar attr
+specifies the attribute code of the created attribute.
+.Pp
+Argument
+.Ar pc_value
+contains a relocatable address which will become the value of the
+created attribute.
+.Pp
+Argument
+.Ar sym_index
+should specify the ELF symbol index of the symbol to be used when
+relocating the address value.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_add_AT_ref_address
+returns the created attribute descriptor.
+In case of an error, function
+.Fn dwarf_add_AT_ref_address
+returns
+.Dv DW_DLV_BADADDR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_add_AT_ref_address
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Either of the arguments
+.Ar dbg
+or
+.Ar die
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during execution.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_AT_dataref 3 ,
+.Xr dwarf_add_AT_reference 3 ,
+.Xr dwarf_add_AT_signed_const 3 ,
+.Xr dwarf_add_AT_unsigned_const 3 ,
+.Xr dwarf_new_die 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_AT_reference.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,117 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_AT_reference.3 2072 2011-10-27 03:26:49Z jkoshy $
+.\"
+.Dd September 4, 2011
+.Os
+.Dt DWARF_ADD_AT_REFERENCE 3
+.Sh NAME
+.Nm dwarf_add_AT_reference
+.Nd create and attach an attribute that references another DIE
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "Dwarf_P_Attribute"
+.Fo dwarf_add_AT_reference
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_P_Die die"
+.Fa "Dwarf_Half attr"
+.Fa "Dwarf_P_Die ref_die"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_add_AT_reference
+creates an attribute descriptor that references another debugging
+information entry in the same compilation unit.
+The attribute will be of DWARF form
+.Dv DW_FORM_ref4
+or
+.Dv DW_FORM_ref8
+depending on the target address size, and will contain the
+section-relative offset of the referenced debugging information entry
+as its value.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar die
+should reference a debugging information entry allocated using
+.Xr dwarf_new_die 3 .
+.Pp
+Argument
+.Ar attr
+should specify the attribute code of the created attribute descriptor.
+.Pp
+Argument
+.Ar ref_die
+should hold the debugging information entry descriptor that
+the attribute should refer to.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_add_AT_reference
+returns the created attribute descriptor.
+In case of an error, function
+.Fn dwarf_add_AT_reference
+returns
+.Dv DW_DLV_BADADDR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_add_AT_reference
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar dbg ,
+.Ar die
+or
+.Ar ref_die
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of
+the function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_AT_dataref 3 ,
+.Xr dwarf_add_AT_ref_address 3 ,
+.Xr dwarf_add_AT_signed_const 3 ,
+.Xr dwarf_add_AT_unsigned_const 3 ,
+.Xr dwarf_new_die 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_AT_signed_const.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,131 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_AT_signed_const.3 2072 2011-10-27 03:26:49Z jkoshy $
+.\"
+.Dd September 4, 2011
+.Os
+.Dt DWARF_ADD_AT_SIGNED_CONST 3
+.Sh NAME
+.Nm dwarf_add_AT_signed_const ,
+.Nm dwarf_add_AT_unsigned_const
+.Nd create and attach constant class attributes
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft Dwarf_P_Attribute
+.Fo dwarf_add_AT_signed_const
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_P_Die die"
+.Fa "Dwarf_Half attr"
+.Fa "Dwarf_Signed value"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft Dwarf_P_Attribute
+.Fo dwarf_add_AT_unsigned_const
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_P_Die die"
+.Fa "Dwarf_Half attr"
+.Fa "Dwarf_Unsigned value"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+These functions create attribute descriptors belonging to the
+.Sq constant
+class
+and attach them to the debugging information entry referenced by
+argument
+.Ar die .
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar die
+should reference a debugging information entry allocated using
+.Xr dwarf_new_die 3 .
+.Pp
+Argument
+.Ar attr
+specifies the attribute code of the created attribute descriptor.
+.Pp
+Function
+.Fn dwarf_add_AT_signed_const
+creates an attribute descriptor with the signed value specified in
+argument
+.Ar value .
+.Pp
+Function
+.Fn dwarf_add_AT_unsigned_const
+creates an attribute descriptor with the unsigned value specified in
+argument
+.Ar value .
+.Pp
+The attribute created by these function will have one of the
+DWARF forms
+.Dv DW_FORM_data1 ,
+.Dv DW_FORM_data2 ,
+.Dv DW_FORM_data4
+or
+.Dv DW_FORM_data8 ,
+depending on the size of the value specified in argument
+.Ar value .
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used by these functions to store error
+information in case of an error.
+.Sh RETURN VALUES
+On success, these functions return the created attribute descriptor.
+In case of an error, these functions return
+.Dv DW_DLV_BADADDR
+and set the argument
+.Ar err .
+.Sh ERRORS
+These functions can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Either of the arguments
+.Ar dbg
+or
+.Ar die
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during execution.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_AT_const_value_signedint 3 ,
+.Xr dwarf_add_AT_const_value_unsignedint 3 ,
+.Xr dwarf_add_AT_dataref 3 ,
+.Xr dwarf_add_AT_ref_address 3 ,
+.Xr dwarf_add_AT_targ_address_b 3 ,
+.Xr dwarf_new_die 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_AT_string.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,114 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_AT_string.3 2072 2011-10-27 03:26:49Z jkoshy $
+.\"
+.Dd September 4, 2011
+.Os
+.Dt DWARF_ADD_AT_STRING 3
+.Sh NAME
+.Nm dwarf_add_AT_string
+.Nd create and attach a string class attribute
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft Dwarf_P_Attribute
+.Fo dwarf_add_AT_string
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_P_Die die"
+.Fa "Dwarf_Half attr"
+.Fa "char *str"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_add_AT_string
+creates an attribute descriptor belonging to the
+.Sq string
+class and attaches it to the debugging information entry referenced by
+argument
+.Ar die .
+The created attribute descriptor will have DWARF form
+.Dv DW_FORM_strp .
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar die
+should reference a debugging information entry allocated using
+.Xr dwarf_new_die 3 .
+.Pp
+Argument
+.Ar attr
+should specify the attribute code for the created attribute
+descriptor.
+.Pp
+Argument
+.Ar str
+should hold a pointer to a NUL-terminated string which will become the
+value of the created attribute descriptor.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_add_AT_string
+returns the created attribute descriptor.
+In case of an error, function
+.Fn dwarf_add_AT_string
+returns
+.Dv DW_DLV_BADADDR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_add_AT_string
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar dbg ,
+.Ar die
+or
+.Ar str
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of
+the function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_AT_const_value_string 3 ,
+.Xr dwarf_add_AT_name 3 ,
+.Xr dwarf_new_die 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_AT_targ_address.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,137 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_AT_targ_address.3 2072 2011-10-27 03:26:49Z jkoshy $
+.\"
+.Dd September 4, 2011
+.Os
+.Dt DWARF_ADD_AT_TARG_ADDRESS 3
+.Sh NAME
+.Nm dwarf_add_AT_targ_address ,
+.Nm dwarf_add_AT_targ_address_b
+.Nd create and attach address class attributes
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft Dwarf_P_Attribute
+.Fo dwarf_add_AT_targ_address
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_P_Die die"
+.Fa "Dwarf_Half attr"
+.Fa "Dwarf_Unsigned pc_value"
+.Fa "Dwarf_Signed sym_index"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft Dwarf_P_Attribute
+.Fo dwarf_add_AT_targ_address_b
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_P_Die die"
+.Fa "Dwarf_Half attr"
+.Fa "Dwarf_Unsigned pc_value"
+.Fa "Dwarf_Unsigned sym_index"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_add_AT_targ_address_b
+creates an attribute descriptor belonging to the
+.Sq address
+class and attaches it to the debugging information entry referenced by
+argument
+.Ar die .
+.Pp
+The created attribute descriptor will have DWARF form
+.Dv DW_FORM_addr .
+If flag
+.Dv DW_DLC_SIZE_64
+is set on the producer instance, the attribute value will be 8 bytes
+in size.
+Otherwise the attribute value will be 4 bytes in size.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar die
+should reference a debugging information entry allocated using
+.Xr dwarf_new_die 3 .
+.Pp
+Argument
+.Ar attr
+should specify the attribute code of the created attribute descriptor.
+.Pp
+Argument
+.Ar pc_value
+should hold a relocatable address value which will become the value of
+the created attribute descriptor.
+.Pp
+Argument
+.Ar sym_index
+should specify the ELF symbol index of the symbol to be used for
+relocating the address value.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Pp
+Function
+.Fn dwarf_add_AT_targ_address
+is deprecated.
+It is similar to function
+.Fn dwarf_add_AT_targ_address_b
+except that it cannot handle all possible symbol index values.
+.Sh RETURN VALUES
+On success, these functions return the created attribute descriptor.
+In case of an error, these functions return
+.Dv DW_DLV_BADADDR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+These functions can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Either of the arguments
+.Ar dbg
+or
+.Ar die
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during execution.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_AT_const_value_unsignedint 3 ,
+.Xr dwarf_add_AT_dataref 3 ,
+.Xr dwarf_add_AT_ref_address 3 ,
+.Xr dwarf_add_AT_signed_const 3 ,
+.Xr dwarf_add_AT_unsigned_const 3 ,
+.Xr dwarf_new_die 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_arange.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,151 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_arange.3 2072 2011-10-27 03:26:49Z jkoshy $
+.\"
+.Dd September 18, 2011
+.Os
+.Dt DWARF_ADD_ARANGE 3
+.Sh NAME
+.Nm dwarf_add_arange ,
+.Nm dwarf_add_arange_b
+.Nd add address range information to a DWARF producer instance
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "Dwarf_Unsigned"
+.Fo dwarf_add_arange
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_Addr start"
+.Fa "Dwarf_Unsigned length"
+.Fa "Dwarf_Signed symbol_index"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft "Dwarf_Unsigned"
+.Fo dwarf_add_arange_b
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_Addr start"
+.Fa "Dwarf_Unsigned length"
+.Fa "Dwarf_Unsigned symbol_index"
+.Fa "Dwarf_Unsigned end_symbol_index"
+.Fa "Dwarf_Addr offset_from_end_symbol"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_add_arange_b
+adds an address range entry to a producer instance.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar start
+specifies the relocatable start address of the address range.
+.Pp
+Argument
+.Ar length
+specifies the length of the address range.
+.Pp
+Argument
+.Ar symbol_index
+specifies the ELF symbol index of the first symbol to be used for
+relocation.
+.Pp
+Argument
+.Ar end_symbol_index
+specifies the ELF symbol index of the second symbol to be used for
+relocation.
+.Bl -bullet
+.It
+If argument
+.Ar end_symbol_index
+is not 0, the
+.Dv DW_DLC_SYMBOLIC_RELOCATIONS
+flag should have been set on the DWARF producer instance.
+The address value specified by argument
+.Ar start
+will be treated as an offset value from the first symbol,
+and the argument
+.Ar offset_from_end_symbol
+should hold an offset value from the second symbol.
+Application code can retrieve the relocation entries for the
+symbol pair by calling function
+.Xr dwarf_get_relocation_info 3 .
+The relocation entry for the first symbol will have type
+.Dv dwarf_drt_first_of_length_pair
+and the relocation entry for the second symbol will have type
+.Dv dwarf_drt_second_of_length_pair .
+.It
+If argument
+.Ar end_symbol_index
+is 0, argument
+.Ar offset_from_end_symbol
+will be ignored and only one symbol is used for relocation.
+.El
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Pp
+Function
+.Fn dwarf_add_arange
+is deprecated.
+It is similar to function
+.Fn dwarf_add_arange_b
+except that it cannot handle all possible symbol index values
+and supports only one relocation symbol.
+.Sh RETURN VALUES
+On success, these functions return a non-zero value.
+In case of an error, these functions return 0 and set
+the argument
+.Ar err .
+.Sh ERRORS
+These functions can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Ar dbg
+was NULL.
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Ar end_symbol_index
+was non-zero, but the flag
+.Dv DW_DLC_SYMBOLIC_RELOCATIONS
+was not set on the producer instance.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_relocation_info 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_die_to_debug.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,95 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_die_to_debug.3 2938 2013-04-27 05:09:17Z jkoshy $
+.\"
+.Dd August 21, 2011
+.Os
+.Dt DWARF_ADD_DIE_TO_DEBUG 3
+.Sh NAME
+.Nm dwarf_add_die_to_debug
+.Nd set the root debugging information entry
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft Dwarf_Unsigned
+.Fo dwarf_add_die_to_debug
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_P_Die first_die"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_add_die_to_debug
+sets the root debugging information entry of a DWARF producer
+instance.
+All debugging information entries linked to the root entry will also
+be added to the producer instance.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar first_die
+should hold the debugging information entry which will become
+the root DIE.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_add_die_to_debug
+returns
+.Dv DW_DLV_OK .
+In case of an error, function
+.Fn dwarf_add_die_to_debug
+returns
+.Dv DW_DLV_NOCOUNT
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_add_die_to_debug
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Either of the arguments
+.Ar dbg
+or
+.Ar first_die
+was NULL.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_die_link 3 ,
+.Xr dwarf_new_die 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_directory_decl.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,97 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_directory_decl.3 2072 2011-10-27 03:26:49Z jkoshy $
+.\"
+.Dd September 17, 2011
+.Os
+.Dt DWARF_ADD_DIRECTORY_DECL 3
+.Sh NAME
+.Nm dwarf_add_directory_decl
+.Nd add a directory name to a producer instance
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "Dwarf_Unsigned"
+.Fo dwarf_add_directory_decl
+.Fa "Dwarf_P_Debug dbg"
+.Fa "char *name"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_add_directory_decl
+adds a source directory name to a producer instance and returns the
+index value generated for the directory name.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar name
+should point a NUL-terminated string containing the name of
+the directory.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_add_directory_decl
+returns the index value generated for the directory.
+In case of an error, function
+.Fn dwarf_add_directory_decl
+returns
+.Dv DW_DLV_NOCOUNT
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_add_directory_decl
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Either of the arguments
+.Ar dbg
+or
+.Ar name
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_file_decl 3 ,
+.Xr dwarf_add_line_entry 3 ,
+.Xr dwarf_lne_end_sequence 3 ,
+.Xr dwarf_lne_set_address 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_expr_addr.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,111 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_expr_addr.3 2072 2011-10-27 03:26:49Z jkoshy $
+.\"
+.Dd September 9, 2011
+.Os
+.Dt DWARF_ADD_EXPR_ADDR 3
+.Sh NAME
+.Nm dwarf_add_expr_addr ,
+.Nm dwarf_add_expr_addr_b
+.Nd add a DW_OP_addr location expression
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "Dwarf_Unsigned"
+.Fo dwarf_add_expr_addr
+.Fa "Dwarf_P_Expr expr"
+.Fa "Dwarf_Unsigned address"
+.Fa "Dwarf_Signed sym_index"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft "Dwarf_Unsigned"
+.Fo dwarf_add_expr_addr_b
+.Fa "Dwarf_P_Expr expr"
+.Fa "Dwarf_Unsigned address"
+.Fa "Dwarf_Unsigned sym_index"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_add_expr_addr_b
+adds a
+.Dv DW_OP_addr
+location expression to the location expression descriptor referenced
+by argument
+.Ar expr .
+.Pp
+Argument
+.Ar expr
+should reference a location expression descriptor allocated using
+the function
+.Xr dwarf_new_expr 3 .
+.Pp
+Argument
+.Ar address
+specifies the operand, a relocatable address value.
+.Pp
+Argument
+.Ar sym_index
+specifies the ELF symbol index of the symbol to be used for
+relocation.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Pp
+Function
+.Fn dwarf_add_expr_addr
+is deprecated.
+It is similar to function
+.Fn dwarf_add_expr_addr_b
+except that it cannot handle all possible symbol index values.
+.Sh RETURN VALUES
+On success, these functions return the size in bytes of the location
+expression byte stream generated.
+In case of an error, these functions return
+.Dv DW_DLV_NOCOUNT
+and set the argument
+.Ar err .
+.Sh ERRORS
+These functions can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Ar expr
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of
+the function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_AT_location_expr 3 ,
+.Xr dwarf_add_expr_gen 3 ,
+.Xr dwarf_expr_current_offset 3 ,
+.Xr dwarf_expr_into_block 3 ,
+.Xr dwarf_new_expr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_expr_gen.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,118 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_expr_gen.3 2072 2011-10-27 03:26:49Z jkoshy $
+.\"
+.Dd September 9, 2011
+.Os
+.Dt DWARF_ADD_EXPR_GEN 3
+.Sh NAME
+.Nm dwarf_add_expr_gen
+.Nd add an operator to a location expression descriptor
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "Dwarf_Unsigned"
+.Fo dwarf_add_expr_gen
+.Fa "Dwarf_P_Expr expr"
+.Fa "Dwarf_Small opcode"
+.Fa "Dwarf_Unsigned val1"
+.Fa "Dwarf_Unsigned val2"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_add_expr_gen
+adds a location expression operator to the location expression
+descriptor referenced by argument
+.Ar expr .
+.Pp
+Argument
+.Ar expr
+should reference a location expression descriptor allocated using
+the function
+.Xr dwarf_new_expr 3 .
+.Pp
+Argument
+.Ar opcode
+specifies the operation code of the location expression operator.
+Valid values for this argument are those denoted by the
+.Dv DW_OP_ Ns *
+constants defined in
+.In libdwarf.h .
+.Pp
+To generate a
+.Dv DW_OP_addr
+operation, application code should instead use
+.Xr dwarf_add_expr_addr_b 3 .
+.Pp
+Argument
+.Ar val1
+specifies the first operand of the location expression operator.
+.Pp
+Argument
+.Ar val2
+specifies the second operand of the location expression operator.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_add_expr_gen
+returns the size in bytes of the location expression byte stream
+generated.
+In case of an error, function
+.Fn dwarf_add_expr_gen
+returns
+.Dv DW_DLV_NOCOUNT
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_add_expr_gen
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_LOC_EXPR_BAD"
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Ar expr
+was NULL.
+.It Bq Er DW_DLE_LOC_EXPR_BAD
+The operation code specified in argument
+.Ar opcode
+was invalid.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of
+the function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_AT_location_expr 3 ,
+.Xr dwarf_add_expr_addr 3 ,
+.Xr dwarf_add_expr_addr_b 3 ,
+.Xr dwarf_expr_current_offset 3 ,
+.Xr dwarf_expr_into_block 3 ,
+.Xr dwarf_new_expr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_fde_inst.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,113 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_fde_inst.3 2072 2011-10-27 03:26:49Z jkoshy $
+.\"
+.Dd September 26, 2011
+.Os
+.Dt DWARF_ADD_FDE_INST 3
+.Sh NAME
+.Nm dwarf_add_fde_inst
+.Nd add a call frame instruction to a DWARF frame descriptor
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "Dwarf_P_Fde"
+.Fo dwarf_add_fde_inst
+.Fa "Dwarf_P_Fde fde"
+.Fa "Dwarf_Small op"
+.Fa "Dwarf_Unsigned val1"
+.Fa "Dwarf_Unsigned val2"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_add_fde_inst
+adds a call frame instruction to the DWARF frame descriptor
+referenced by argument
+.Ar fde .
+.Pp
+Argument
+.Ar fde
+should reference a frame descriptor allocated using
+.Xr dwarf_new_fde 3 .
+.Pp
+Argument
+.Ar op
+specifies the operator for the frame instruction.
+The DWARF standard defines the set of legal values for this argument.
+.Pp
+Argument
+.Ar val1
+specifies the first operand of the frame instruction.
+.Pp
+Argument
+.Ar val2
+specifies the second operand of the frame instruction.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_add_fde_inst
+returns the frame descriptor given in argument
+.Ar fde .
+In case of an error, function
+.Fn dwarf_add_fde_inst
+returns
+.Dv DW_DLV_BADADDR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_add_fde_inst
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_FRAME_INSTR_EXEC_ERROR"
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Ar fde
+was NULL.
+.It Bq Er DW_DLE_FRAME_INSTR_EXEC_ERROR
+The frame instruction operator specified in argument
+.Ar op
+was invalid.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_frame_fde 3 ,
+.Xr dwarf_add_frame_fde_b 3 ,
+.Xr dwarf_add_frame_cie 3 ,
+.Xr dwarf_fde_cfa_offset 3 ,
+.Xr dwarf_new_fde 3
+.Rs
+.%T "The DWARF Debugging Information Format"
+.%V "Version 4"
+.%O "http://www.dwarfstd.org/"
+.Re
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_file_decl.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,122 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_file_decl.3 2072 2011-10-27 03:26:49Z jkoshy $
+.\"
+.Dd September 17, 2011
+.Os
+.Dt DWARF_ADD_FILE_DECL 3
+.Sh NAME
+.Nm dwarf_add_file_decl
+.Nd add a source file entry to a producer instance
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "Dwarf_Unsigned"
+.Fo dwarf_add_file_decl
+.Fa "Dwarf_P_Debug dbg"
+.Fa "char *name"
+.Fa "Dwarf_Unsigned dirndx"
+.Fa "Dwarf_Unsigned mtime"
+.Fa "Dwarf_Unsigned size"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_add_file_decl
+adds a source file entry to a producer instance.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar name
+should point to a NUL-terminated string containing the name of
+the source file.
+.Pp
+If the file name in argument
+.Ar name
+is not a fully qualified pathname, argument
+.Ar dirndx
+should specify the index of the directory where the source file resides.
+Otherwise, argument
+.Ar dirndx
+should be 0.
+Valid directory indices are those returned by the function
+.Xr dwarf_add_directory_decl 3 .
+.Pp
+Argument
+.Ar mtime
+specifies the time when the file was last modified.
+.Pp
+Argument
+.Ar size
+specifies the size of the file in bytes.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_add_file_decl
+returns the index value generated for the source file.
+In case of an error, function
+.Fn dwarf_add_file_decl
+returns
+.Dv DW_DLV_NOCOUNT
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_add_file_decl
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Either arguments
+.Ar dbg
+or
+.Ar name
+was NULL.
+.It Bq Er DW_DLE_ARGUMENT
+The length of the NUL-teminated string pointed to by argument
+.Ar name
+was 0.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_directory_decl 3 ,
+.Xr dwarf_add_line_entry 3 ,
+.Xr dwarf_lne_end_sequence 3 ,
+.Xr dwarf_lne_set_address 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_frame_cie.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,124 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_frame_cie.3 2072 2011-10-27 03:26:49Z jkoshy $
+.\"
+.Dd September 26, 2011
+.Os
+.Dt DWARF_ADD_FRAME_CIE 3
+.Sh NAME
+.Nm dwarf_add_frame_cie
+.Nd add a call frame common information entry to a DWARF producer instance
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "Dwarf_Unsigned"
+.Fo dwarf_add_frame_cie
+.Fa "Dwarf_P_Debug dbg"
+.Fa "char *augmenter"
+.Fa "Dwarf_Small caf"
+.Fa "Dwarf_Small daf"
+.Fa "Dwarf_Small ra"
+.Fa "Dwarf_Ptr initinst"
+.Fa "Dwarf_Unsigned initlen"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_add_frame_cie
+adds a DWARF call frame common information entry (CIE) to a producer
+instance.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar augmenter
+should point to a NUL-terminated augmentation string for the common
+information entry.
+.Pp
+Argument
+.Ar caf
+specifies the code alignment factor.
+.Pp
+Argument
+.Ar daf
+specifies the data alignment factor.
+.Pp
+Argument
+.Ar ra
+specifies the column number used for the return address register.
+.Pp
+Argument
+.Ar initinst
+should point to a byte stream containing the initial instructions
+for the common information entry.
+.Pp
+Argument
+.Ar initlen
+should hold the length in bytes of the byte stream pointed to by
+argument
+.Ar initinst .
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_add_frame_cie
+returns the index value of the created common information entry.
+In case of an error, function
+.Fn dwarf_add_frame_cie
+returns
+.Dv DW_DLV_NOCOUNT
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_add_frame_cie
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Ar dbg
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_fde_inst 3 ,
+.Xr dwarf_add_frame_fde 3 ,
+.Xr dwarf_add_frame_fde_b 3 ,
+.Xr dwarf_fde_cfa_offset 3 ,
+.Xr dwarf_new_fde 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_frame_fde.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,201 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_frame_fde.3 2072 2011-10-27 03:26:49Z jkoshy $
+.\"
+.Dd September 26, 2011
+.Os
+.Dt DWARF_ADD_FRAME_FDE 3
+.Sh NAME
+.Nm dwarf_add_frame_fde
+.Nd add a call frame descriptor to a DWARF producer instance
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "Dwarf_Unsigned"
+.Fo dwarf_add_frame_fde
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_P_Fde fde"
+.Fa "Dwarf_P_Die die"
+.Fa "Dwarf_Unsigned cie"
+.Fa "Dwarf_Addr virt_addr"
+.Fa "Dwarf_Unsigned code_len"
+.Fa "Dwarf_Unsigned symbol_index"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft "Dwarf_Unsigned"
+.Fo dwarf_add_frame_fde_b
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_P_Fde fde"
+.Fa "Dwarf_P_Die die"
+.Fa "Dwarf_Unsigned cie"
+.Fa "Dwarf_Addr virt_addr"
+.Fa "Dwarf_Unsigned code_len"
+.Fa "Dwarf_Unsigned symbol_index"
+.Fa "Dwarf_Unsigned end_symbol_index"
+.Fa "Dwarf_Addr offset_from_end_sym"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_add_frame_fde_b
+adds the call frame descriptor referenced by argument
+.Ar fde
+to a producer instance.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar fde
+should reference a frame descriptor allocated using
+.Xr dwarf_new_fde 3 .
+.Pp
+Argument
+.Ar die
+is ignored by this implementation of the
+.Lb libdwarf .
+.Pp
+Argument
+.Ar cie
+specifies the index of call frame common information entry for
+the frame descriptor.
+Valid indices are those returned by the function
+.Xr dwarf_add_frame_cie 3 .
+.Pp
+Argument
+.Ar symbol_index
+specifies the ELF symbol index of the first symbol to be used for
+relocation.
+.Pp
+The meaning of the arguments
+.Ar virt_addr ,
+.Ar code_len
+and
+.Ar offset_from_end_sym
+depend on the value of argument
+.Ar end_symbol_index :
+.Bl -bullet
+.It
+If the argument
+.Ar end_symbol_index
+is zero, the argument
+.Ar virt_addr
+specifies the relocatable address of the start of the function
+associated with the frame descriptor, the argument
+.Ar code_len
+specifies the size in bytes of the machine instructions for this
+function, the argument
+.Ar symbol_index
+specifies the ELF symbol to be used for relocating the address in
+argument
+.Ar virt_addr ,
+and the argument
+.Ar offset_from_end_symbol
+is ignored.
+.It
+If the argument
+.Ar end_symbol_index
+is non-zero, it specifies the ELF symbol index of the second symbol to
+be used for relocation.
+In this case, the argument
+.Ar virt_addr
+specifies an offset from the relocatable symbol specified by argument
+.Ar symbol_index ,
+the argument
+.Ar offset_from_end_symbol
+should specify an offset from the symbol named by the argument
+.Ar end_symbol_index ,
+and the argument
+.Ar code_len
+will be ignored.
+The
+.Dv DW_DLC_SYMBOLIC_RELOCATIONS
+flag should also have been set on the DWARF producer instance.
+.Pp
+Application code can retrieve the relocation entries for the symbol
+pair by calling function
+.Xr dwarf_get_relocation_info 3 .
+The relocation entry for the first symbol will have type
+.Dv dwarf_drt_first_of_length_pair
+and the relocation entry for the second symbol will have type
+.Dv dwarf_drt_second_of_length_pair .
+.El
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Pp
+Function
+.Fn dwarf_add_frame_fde
+is similar to function
+.Fn dwarf_add_frame_fde_b
+except that it supports only one relocation symbol.
+.Sh RETURN VALUES
+On success, these functions return the index value for
+the added frame descriptor.
+In case of an error, these functions return
+.Dv DW_DLV_NOCOUNT
+and set the argument
+.Ar err .
+.Sh ERRORS
+These functions can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar dbg
+or
+.Ar fde
+was NULL.
+.It Bq Er DW_DLE_ARGUMENT
+The frame descriptor referenced by argument
+.Ar fde
+did not belong to the producer instance referenced by argument
+.Ar dbg .
+.It Bq Er DW_DLE_ARGUMENT
+The common information entry index specified by argument
+.Ar cie
+was invalid.
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Ar end_symbol_index
+was non-zero, but the flag
+.Dv DW_DLC_SYMBOLIC_RELOCATIONS
+was not set on the producer instance.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_fde_inst 3 ,
+.Xr dwarf_add_frame_cie 3 ,
+.Xr dwarf_fde_cfa_offset 3 ,
+.Xr dwarf_get_relocation_info 3 ,
+.Xr dwarf_new_fde 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_funcname.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,103 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_funcname.3 2072 2011-10-27 03:26:49Z jkoshy $
+.\"
+.Dd September 24, 2011
+.Os
+.Dt DWARF_ADD_FUNCNAME 3
+.Sh NAME
+.Nm dwarf_add_funcname
+.Nd add information about a static function to a DWARF producer instance
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "Dwarf_Unsigned"
+.Fo dwarf_add_funcname
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_P_Die die"
+.Fa "char *name"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_add_funcname
+adds information about a static function to a DWARF producer instance.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar die
+specifies the debugging information entry associated with the static
+function.
+.Pp
+Argument
+.Ar name
+should point to a NUL-terminated string containing the name
+of the static function.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_add_funcname
+returns a non-zero value.
+In case of an error, function
+.Fn dwarf_add_funcname
+returns 0 and sets
+the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_add_funcname
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar dbg ,
+.Ar die
+or
+.Ar name
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_pubname 3 ,
+.Xr dwarf_add_typename 3 ,
+.Xr dwarf_add_varname 3 ,
+.Xr dwarf_add_weakname 3 ,
+.Xr dwarf_new_die 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_line_entry.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,164 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_line_entry.3 3182 2015-04-10 16:08:10Z emaste $
+.\"
+.Dd June 30, 2013
+.Os
+.Dt DWARF_ADD_LINE_ENTRY 3
+.Sh NAME
+.Nm dwarf_add_line_entry
+.Nd add a line number information entry to a producer instance
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "Dwarf_Unsigned"
+.Fo dwarf_add_line_entry
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_Unsigned filendx"
+.Fa "Dwarf_Addr off"
+.Fa "Dwarf_Unsigned lineno"
+.Fa "Dwarf_Signed column"
+.Fa "Dwarf_Bool is_stmt"
+.Fa "Dwarf_Bool basic_block"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_add_line_entry
+adds a line number information entry to a DWARF producer instance.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar filendx
+specifies the index of the source file that contains the source line
+in question.
+Valid source file indices are those returned by the function
+.Xr dwarf_add_file_decl 3 .
+.Pp
+Argument
+.Ar off
+specifies a relocatable program address.
+The ELF symbol to be used
+for relocation is set by a prior call to the function
+.Xr dwarf_lne_set_address 3 .
+.Pp
+Argument
+.Ar lineno
+specifies the line number of the source line.
+.Pp
+Argument
+.Ar column
+specifies the column number within the source line.
+.Pp
+If the argument
+.Ar is_stmt
+is set to true, it indicates that the instruction at the address
+specified by argument
+.Ar off
+is a recommended breakpoint location, i.e., the first instruction in
+the instruction sequence generated by the source line.
+.Pp
+If the argument
+.Ar basic_block
+is set to true, it indicates that the instruction at the address
+specified by argument
+.Ar off
+is the first instruction of a basic block.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_add_line_entry
+returns
+.Dv DW_DLV_OK .
+In case of an error, function
+.Fn dwarf_add_line_entry
+returns
+.Dv DW_DLV_NOCOUNT
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_add_line_entry
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Ar dbg
+was NULL.
+.It Bq Er DW_DLE_ARGUMENT
+The function
+.Xr dwarf_lne_set_address 3
+was not called before calling this function.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh EXAMPLE
+To add line number information to the producer instance, use:
+.Bd -literal -offset indent
+Dwarf_P_Debug dbg;
+Dwarf_Error de;
+Dwarf_Unsigned dir, filendx;
+
+/* ... assume dbg refers to a DWARF producer instance ... */
+
+dir = dwarf_add_directory_decl(dbg, "/home/foo", &de);
+if (dir == DW_DLV_NOCOUNT)
+	errx(EXIT_FAILURE, "dwarf_add_directory_decl failed: %s",
+	    dwarf_errmsg(-1));
+
+filendx = dwarf_add_file_decl(dbg, "bar.c", dir, 0, 1234, &de);
+if (filendx == DW_DLV_NOCOUNT)
+	errx(EXIT_FAILURE, "dwarf_add_file_decl failed: %s",
+	    dwarf_errmsg(-1));
+
+if (dwarf_lne_set_address(dbg, 0x4012b0, 12, &de) != DW_DLV_OK)
+	errx(EXIT_FAILURE, "dwarf_lne_set_address failed: %s",
+	    dwarf_errmsg(-1));
+
+if (dwarf_add_line_entry(dbg, filendx, 10, 258, 0, 1, 1, &de) !=
+    DW_DLV_OK)
+	errx(EXIT_FAILURE, "dwarf_add_line_entry failed: %s",
+	    dwarf_errmsg(-1));
+.Ed
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_directory_decl 3 ,
+.Xr dwarf_add_file_decl 3 ,
+.Xr dwarf_lne_end_sequence 3 ,
+.Xr dwarf_lne_set_address 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_pubname.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,103 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_pubname.3 2072 2011-10-27 03:26:49Z jkoshy $
+.\"
+.Dd September 24, 2011
+.Os
+.Dt DWARF_ADD_PUBNAME 3
+.Sh NAME
+.Nm dwarf_add_pubname
+.Nd add information about a global object to a DWARF producer instance
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "Dwarf_Unsigned"
+.Fo dwarf_add_pubname
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_P_Die die"
+.Fa "char *name"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_add_pubname
+adds information about a global object to a DWARF producer instance.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar die
+specifies the debugging information entry associated with the global
+object.
+.Pp
+Argument
+.Ar name
+should point to a NUL-terminated string containing the name
+of the global object.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_add_pubname
+returns a non-zero value.
+In case of an error, function
+.Fn dwarf_add_pubname
+returns 0 and sets
+the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_add_pubname
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar dbg ,
+.Ar die
+or
+.Ar name
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_funcname 3 ,
+.Xr dwarf_add_typename 3 ,
+.Xr dwarf_add_varname 3 ,
+.Xr dwarf_add_weakname 3 ,
+.Xr dwarf_new_die 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_typename.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,103 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_typename.3 2072 2011-10-27 03:26:49Z jkoshy $
+.\"
+.Dd September 24, 2011
+.Os
+.Dt DWARF_ADD_TYPENAME 3
+.Sh NAME
+.Nm dwarf_add_typename
+.Nd add information about a user-defined type to a DWARF producer instance
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "Dwarf_Unsigned"
+.Fo dwarf_add_typename
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_P_Die die"
+.Fa "char *name"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_add_typename
+adds information about a user-defined type to a DWARF producer instance.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar die
+specifies the debugging information entry associated with the
+user-defined type.
+.Pp
+Argument
+.Ar name
+should point to a NUL-terminated string containing the name
+of the user-defined type.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_add_typename
+returns a non-zero value.
+In case of an error, function
+.Fn dwarf_add_typename
+returns 0 and sets
+the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_add_typename
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar dbg ,
+.Ar die
+or
+.Ar name
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_funcname 3 ,
+.Xr dwarf_add_pubname 3 ,
+.Xr dwarf_add_varname 3 ,
+.Xr dwarf_add_weakname 3 ,
+.Xr dwarf_new_die 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_varname.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,103 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_varname.3 2072 2011-10-27 03:26:49Z jkoshy $
+.\"
+.Dd September 24, 2011
+.Os
+.Dt DWARF_ADD_VARNAME 3
+.Sh NAME
+.Nm dwarf_add_varname
+.Nd add information about a static variable to a DWARF producer instance
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "Dwarf_Unsigned"
+.Fo dwarf_add_varname
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_P_Die die"
+.Fa "char *name"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_add_varname
+adds information about a static variable to a DWARF producer instance.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar die
+specifies the debugging information entry associated with the static
+variable.
+.Pp
+Argument
+.Ar name
+should point to a NUL-terminated string containing the name
+of the static variable.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_add_varname
+returns a non-zero value.
+In case of an error, function
+.Fn dwarf_add_varname
+returns 0 and sets
+the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_add_varname
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar dbg ,
+.Ar die
+or
+.Ar name
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_funcname 3 ,
+.Xr dwarf_add_pubname 3 ,
+.Xr dwarf_add_typename 3 ,
+.Xr dwarf_add_weakname 3 ,
+.Xr dwarf_new_die 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_add_weakname.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,103 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_add_weakname.3 2072 2011-10-27 03:26:49Z jkoshy $
+.\"
+.Dd September 24, 2011
+.Os
+.Dt DWARF_ADD_WEAKNAME 3
+.Sh NAME
+.Nm dwarf_add_weakname
+.Nd add information about a weak object to a DWARF producer instance
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "Dwarf_Unsigned"
+.Fo dwarf_add_weakname
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_P_Die die"
+.Fa "char *name"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_add_weakname
+adds information about a weak object to a DWARF producer instance.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar die
+specifies the debugging information entry associated with the weak
+object.
+.Pp
+Argument
+.Ar name
+should point to a NUL-terminated string containing the name
+of the weak object.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_add_weakname
+returns a non-zero value.
+In case of an error, function
+.Fn dwarf_add_weakname
+returns 0 and sets
+the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_add_weakname
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar dbg ,
+.Ar die
+or
+.Ar name
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_funcname 3 ,
+.Xr dwarf_add_pubname 3 ,
+.Xr dwarf_add_typename 3 ,
+.Xr dwarf_add_varname 3 ,
+.Xr dwarf_new_die 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_arange.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,171 @@
+/*-
+ * Copyright (c) 2009,2011 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_arange.c 2072 2011-10-27 03:26:49Z jkoshy $");
+
+int
+dwarf_get_aranges(Dwarf_Debug dbg, Dwarf_Arange **arlist,
+    Dwarf_Signed *ret_arange_cnt, Dwarf_Error *error)
+{
+
+	if (dbg == NULL || arlist == NULL || ret_arange_cnt == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (dbg->dbg_arange_cnt == 0) {
+		if (_dwarf_arange_init(dbg, error) != DW_DLE_NONE)
+			return (DW_DLV_ERROR);
+		if (dbg->dbg_arange_cnt == 0) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+			return (DW_DLV_NO_ENTRY);
+		}
+	}
+
+	assert(dbg->dbg_arange_array != NULL);
+
+	*arlist = dbg->dbg_arange_array;
+	*ret_arange_cnt = dbg->dbg_arange_cnt;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_arange(Dwarf_Arange *arlist, Dwarf_Unsigned arange_cnt,
+    Dwarf_Addr addr, Dwarf_Arange *ret_arange, Dwarf_Error *error)
+{
+	Dwarf_Arange ar;
+	Dwarf_Debug dbg;
+	int i;
+
+	if (arlist == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	dbg = (*arlist)->ar_as->as_cu->cu_dbg;
+
+	if (ret_arange == NULL || arange_cnt == 0) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	for (i = 0; (Dwarf_Unsigned)i < arange_cnt; i++) {
+		ar = arlist[i];
+		if (addr >= ar->ar_address && addr < ar->ar_address +
+		    ar->ar_range) {
+			*ret_arange = ar;
+			return (DW_DLV_OK);
+		}
+	}
+
+	DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+
+	return (DW_DLV_NO_ENTRY);
+}
+
+int
+dwarf_get_cu_die_offset(Dwarf_Arange ar, Dwarf_Off *ret_offset,
+    Dwarf_Error *error)
+{
+	Dwarf_CU cu;
+	Dwarf_ArangeSet as;
+
+	if (ar == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	as = ar->ar_as;
+	assert(as != NULL);
+	cu = as->as_cu;
+	assert(cu != NULL);
+
+	if (ret_offset == NULL) {
+		DWARF_SET_ERROR(cu->cu_dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*ret_offset = cu->cu_1st_offset;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_arange_cu_header_offset(Dwarf_Arange ar, Dwarf_Off *ret_offset,
+    Dwarf_Error *error)
+{
+	Dwarf_ArangeSet as;
+
+	if (ar == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	as = ar->ar_as;
+	assert(as != NULL);
+
+	if (ret_offset == NULL) {
+		DWARF_SET_ERROR(as->as_cu->cu_dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*ret_offset = as->as_cu_offset;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_arange_info(Dwarf_Arange ar, Dwarf_Addr *start,
+    Dwarf_Unsigned *length, Dwarf_Off *cu_die_offset, Dwarf_Error *error)
+{
+	Dwarf_CU cu;
+	Dwarf_ArangeSet as;
+
+	if (ar == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	as = ar->ar_as;
+	assert(as != NULL);
+	cu = as->as_cu;
+	assert(cu != NULL);
+
+	if (start == NULL || length == NULL ||
+	    cu_die_offset == NULL) {
+		DWARF_SET_ERROR(cu->cu_dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*start = ar->ar_address;
+	*length = ar->ar_range;
+	*cu_die_offset = cu->cu_1st_offset;
+
+	return (DW_DLV_OK);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_attr.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,120 @@
+.\" Copyright (c) 2010 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_attr.3 3093 2014-09-02 22:09:40Z kaiwang27 $
+.\"
+.Dd April 8, 2010
+.Os
+.Dt DWARF_ATTR 3
+.Sh NAME
+.Nm dwarf_attr
+.Nd retrieve an attribute descriptor associated with a DWARF debugging information entry
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_attr
+.Fa "Dwarf_Die die"
+.Fa "Dwarf_Half attr"
+.Fa "Dwarf_Attribute *atp"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_attr
+retrieves the attribute descriptor for an attribute associated
+with the DWARF debugging information entry descriptor in
+argument
+.Ar die .
+.Pp
+DWARF attribute descriptors are represented by value of the opaque
+type
+.Vt Dwarf_Attribute ,
+see
+.Xr dwarf 3 .
+.Pp
+Argument
+.Ar attr
+names the desired DWARF attribute.
+Legal values for argument
+.Ar attr
+are those denoted by the
+.Dv DW_AT_*
+constants in the DWARF specification.
+.Pp
+Argument
+.Ar atp
+points to a location into which the returned attribute descriptor
+will be written.
+The returned descriptor may then be passed to the form query functions in the
+.Xr dwarf 3
+API set to access the data associated with the attribute.
+.Pp
+If argument
+.Ar err
+is non-NULL, it will be used to return an error descriptor in case
+of an error.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_attr
+returns
+.Dv DW_DLV_OK on success.
+.Pp
+If the debugging information entry descriptor denoted by argument
+.Ar die
+does not contain the named attribute, the function returns
+.Dv DW_DLV_NO_ENTRY
+and sets argument
+.Ar err .
+For other errors, it returns
+.Dv DW_DLV_ERROR
+and sets argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_attr
+can fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Either of arguments
+.Ar die
+or
+.Ar atp
+was NULL.
+.It Bq Er DW_DLE_NO_ENTRY
+Argument
+.Ar die
+had no attribute corresponding to the value
+in argument
+.Ar attr .
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_attrlist 3 ,
+.Xr dwarf_attroffset 3 ,
+.Xr dwarf_hasattr 3 ,
+.Xr dwarf_hasform 3 ,
+.Xr dwarf_whatattr 3 ,
+.Xr dwarf_whatform 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_attr.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,312 @@
+/*-
+ * Copyright (c) 2007 John Birrell (jb@freebsd.org)
+ * Copyright (c) 2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_attr.c 3064 2014-06-06 19:35:55Z kaiwang27 $");
+
+int
+dwarf_attr(Dwarf_Die die, Dwarf_Half attr, Dwarf_Attribute *atp,
+    Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+	Dwarf_Attribute at;
+
+	dbg = die != NULL ? die->die_dbg : NULL;
+
+	if (die == NULL || atp == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if ((at = _dwarf_attr_find(die, attr)) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	*atp = at;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_attrlist(Dwarf_Die die, Dwarf_Attribute **attrbuf,
+    Dwarf_Signed *attrcount, Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+	Dwarf_Debug dbg;
+	int i;
+
+	dbg = die != NULL ? die->die_dbg : NULL;
+
+	if (die == NULL || attrbuf == NULL || attrcount == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (die->die_ab->ab_atnum == 0) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	*attrcount = die->die_ab->ab_atnum;
+
+	if (die->die_attrarray != NULL) {
+		*attrbuf = die->die_attrarray;
+		return (DW_DLV_OK);
+	}
+
+	if ((die->die_attrarray = malloc(*attrcount * sizeof(Dwarf_Attribute)))
+	    == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLV_ERROR);
+	}
+
+	for (i = 0, at = STAILQ_FIRST(&die->die_attr);
+	     i < *attrcount && at != NULL; i++, at = STAILQ_NEXT(at, at_next))
+		die->die_attrarray[i] = at;
+
+	*attrbuf = die->die_attrarray;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_hasattr(Dwarf_Die die, Dwarf_Half attr, Dwarf_Bool *ret_bool,
+    Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+
+	dbg = die != NULL ? die->die_dbg : NULL;
+
+	if (die == NULL || ret_bool == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*ret_bool = (_dwarf_attr_find(die, attr) != NULL);
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_attroffset(Dwarf_Attribute at, Dwarf_Off *ret_off, Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+
+	dbg = at != NULL ? at->at_die->die_dbg : NULL;
+
+	if (at == NULL || ret_off == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*ret_off = at->at_offset;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_lowpc(Dwarf_Die die, Dwarf_Addr *ret_lowpc, Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+	Dwarf_Debug dbg;
+
+	dbg = die != NULL ? die->die_dbg : NULL;
+
+	if (die == NULL || ret_lowpc == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if ((at = _dwarf_attr_find(die, DW_AT_low_pc)) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	*ret_lowpc = at->u[0].u64;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_highpc(Dwarf_Die die, Dwarf_Addr *ret_highpc, Dwarf_Error *error)
+{
+
+	return (dwarf_highpc_b(die, ret_highpc, NULL, NULL, error));
+}
+
+int
+dwarf_highpc_b(Dwarf_Die die, Dwarf_Addr *ret_highpc, Dwarf_Half *ret_form,
+    enum Dwarf_Form_Class *ret_class, Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+	Dwarf_Debug dbg;
+	Dwarf_CU cu;
+
+	dbg = die != NULL ? die->die_dbg : NULL;
+
+	if (die == NULL || ret_highpc == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if ((at = _dwarf_attr_find(die, DW_AT_high_pc)) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	*ret_highpc = at->u[0].u64;
+
+	if (ret_form != NULL) {
+		*ret_form = at->at_form;
+	}
+
+	if (ret_class != NULL) {
+		cu = die->die_cu;
+		*ret_class = dwarf_get_form_class(cu->cu_version,
+		    DW_AT_high_pc, cu->cu_length_size == 4 ? 4 : 8,
+		    at->at_form);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_bytesize(Dwarf_Die die, Dwarf_Unsigned *ret_size, Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+	Dwarf_Debug dbg;
+
+	dbg = die != NULL ? die->die_dbg : NULL;
+
+	if (die == NULL || ret_size == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if ((at = _dwarf_attr_find(die, DW_AT_byte_size)) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	*ret_size = at->u[0].u64;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_bitsize(Dwarf_Die die, Dwarf_Unsigned *ret_size, Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+	Dwarf_Debug dbg;
+
+	dbg = die != NULL ? die->die_dbg : NULL;
+
+	if (die == NULL || ret_size == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if ((at = _dwarf_attr_find(die, DW_AT_bit_size)) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	*ret_size = at->u[0].u64;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_bitoffset(Dwarf_Die die, Dwarf_Unsigned *ret_size, Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+	Dwarf_Debug dbg;
+
+	dbg = die != NULL ? die->die_dbg : NULL;
+
+	if (die == NULL || ret_size == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if ((at = _dwarf_attr_find(die, DW_AT_bit_offset)) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	*ret_size = at->u[0].u64;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_srclang(Dwarf_Die die, Dwarf_Unsigned *ret_lang, Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+	Dwarf_Debug dbg;
+
+	dbg = die != NULL ? die->die_dbg : NULL;
+
+	if (die == NULL || ret_lang == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if ((at = _dwarf_attr_find(die, DW_AT_language)) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	*ret_lang = at->u[0].u64;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_arrayorder(Dwarf_Die die, Dwarf_Unsigned *ret_order, Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+	Dwarf_Debug dbg;
+	
+	dbg = die != NULL ? die->die_dbg : NULL;
+
+	if (die == NULL || ret_order == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if ((at = _dwarf_attr_find(die, DW_AT_ordering)) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	*ret_order = at->u[0].u64;
+
+	return (DW_DLV_OK);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_attrlist.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,146 @@
+.\" Copyright (c) 2010 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_attrlist.3 2122 2011-11-09 15:35:14Z jkoshy $
+.\"
+.Dd November 9, 2011
+.Os
+.Dt DWARF_ATTRLIST 3
+.Sh NAME
+.Nm dwarf_attrlist
+.Nd retrieve DWARF attribute descriptors
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_attrlist
+.Fa "Dwarf_Die die"
+.Fa "Dwarf_Attribute **attrbuf"
+.Fa "Dwarf_Signed *attrcount"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_attrlist
+retrieves the DWARF attribute descriptors associated with a
+debugging information entry descriptor in argument
+.Ar die .
+The descriptors are returned as an array of values of the opaque type
+.Vt Dwarf_Attribute .
+The data associated with each returned attribute descriptor may be
+queried using the form query functions in the
+.Xr dwarf 3
+API set.
+.Pp
+Argument
+.Ar attrbuf
+points to a location that will hold a pointer to the returned
+array of DWARF attribute descriptors.
+Argument
+.Ar attrcount
+points to a location that will hold the number of descriptors in
+the returned array.
+.Pp
+If argument
+.Ar err
+is non-NULL, it is used to return an error descriptor in case of an
+error.
+.Ss Memory Management
+In the current implementation, the memory allocated for each DWARF
+attribute descriptor and for the returned array of descriptors is
+managed by the library and the application does not need to explicitly
+free the returned pointers.
+However, for compatibility with other implementations of the
+.Xr dwarf 3
+API, the application is permitted to pass the pointers returned by to
+the
+.Fn dwarf_dealloc
+function.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_attrlist
+returns
+.Dv DW_DLV_OK on success.
+.Pp
+If the debugging information entry descriptor denoted by argument
+.Ar die
+does not contain any attribute, the function returns
+.Dv DW_DLV_NO_ENTRY
+and sets argument
+.Ar err .
+For other errors, it returns
+.Dv DW_DLV_ERROR
+and sets argument
+.Ar err .
+.Sh EXAMPLES
+To retrieve the attribute list for a DWARF debugging information
+entry use:
+.Bd -literal -offset indent
+Dwarf_Die dw_die;
+Dwarf_Error dw_e;
+Dwarf_Unsigned dw_count;
+Dwarf_Attribute *dw_attributes;
+int error, i;
+
+\&... variable dw_die contains a reference to the DIE of interest ...
+
+/* Retrieve the attribute list from the DIE. */
+if ((error = dwarf_attrlist(dw_die, &dw_attributes, &dw_count,
+	&dw_e)) != DW_DLV_OK)
+	errx(EXIT_FAILURE, "dwarf_attrlist: %s", dwarf_errmsg(dw_e));
+
+/* Process the attribute list. */
+for (i = 0; i < dw_count; ++i) {
+	/* Use the returned pointers in dw_attributes[i] here. */
+}
+.Ed
+.Sh ERRORS
+Function
+.Fn dwarf_diename
+can fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Arguments
+.Ar die ,
+.Ar attrbuf ,
+or
+.Ar attrcount
+were NULL.
+.It Bq Er DW_DLE_NO_ENTRY
+Argument
+.Ar die
+had no attributes.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_attr 3 ,
+.Xr dwarf_dealloc 3 ,
+.Xr dwarf_hasattr 3 ,
+.Xr dwarf_hasform 3 ,
+.Xr dwarf_whatattr 3 ,
+.Xr dwarf_whatform 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_attroffset.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,86 @@
+.\" Copyright (c) 2014 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_attroffset.3 3115 2014-12-20 18:26:46Z jkoshy $
+.\"
+.Dd December 20, 2014
+.Os
+.Dt DWARF_ATTROFFSET 3
+.Sh NAME
+.Nm dwarf_attroffset
+.Nd retrieve the section-relative offset of an attribute descriptor
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_attroffset
+.Fa "Dwarf_Attribute at"
+.Fa "Dwarf_Off *ret_off"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_attroffset
+retrieves the section-relative offset of the attribute descriptor
+referenced by argument
+.Ar at .
+.Pp
+Argument
+.Ar ret_off
+should point to a location that is to hold the returned
+section-relative offset.
+If argument
+.Ar err
+is non-NULL, it is used to return an error descriptor in case of an
+error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_attroffset
+returns
+.Dv DW_DLV_OK .
+.Pp
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets argument
+.Ar err .
+.Sh COMPATIBILITY
+This function is an extension to the
+.Xr DWARF 3
+API.
+.Sh ERRORS
+The
+.Fn dwarf_attroffset
+function may fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Either of the arguments
+.Ar at
+or
+.Ar ret_off
+was NULL.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_attr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_attrval.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,222 @@
+/*-
+ * Copyright (c) 2007 John Birrell (jb@freebsd.org)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_attrval.c 3509 2016-12-29 03:58:41Z emaste $");
+
+int
+dwarf_attrval_flag(Dwarf_Die die, Dwarf_Half attr, Dwarf_Bool *valp, Dwarf_Error *err)
+{
+	Dwarf_Attribute at;
+	Dwarf_Debug dbg;
+
+	dbg = die != NULL ? die->die_dbg : NULL;
+
+	if (die == NULL || valp == NULL) {
+		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*valp = 0;
+
+	if ((at = _dwarf_attr_find(die, attr)) == NULL) {
+		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	switch (at->at_form) {
+	case DW_FORM_flag:
+	case DW_FORM_flag_present:
+		*valp = (Dwarf_Bool) (!!at->u[0].u64);
+		break;
+	default:
+		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
+		return (DW_DLV_ERROR);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_attrval_string(Dwarf_Die die, Dwarf_Half attr, const char **strp, Dwarf_Error *err)
+{
+	Dwarf_Attribute at;
+	Dwarf_Debug dbg;
+
+	dbg = die != NULL ? die->die_dbg : NULL;
+
+	if (die == NULL || strp == NULL) {
+		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*strp = NULL;
+
+	if ((at = _dwarf_attr_find(die, attr)) == NULL) {
+		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	switch (at->at_form) {
+	case DW_FORM_strp:
+		*strp = at->u[1].s;
+		break;
+	case DW_FORM_string:
+		*strp = at->u[0].s;
+		break;
+	default:
+		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
+		return (DW_DLV_ERROR);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_attrval_signed(Dwarf_Die die, Dwarf_Half attr, Dwarf_Signed *valp, Dwarf_Error *err)
+{
+	Dwarf_Attribute at;
+	Dwarf_Debug dbg;
+
+	dbg = die != NULL ? die->die_dbg : NULL;
+
+	if (die == NULL || valp == NULL) {
+		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*valp = 0;
+
+	if ((at = _dwarf_attr_find(die, attr)) == NULL) {
+		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	switch (at->at_form) {
+	case DW_FORM_data1:
+		*valp = (int8_t) at->u[0].s64;
+		break;
+	case DW_FORM_data2:
+		*valp = (int16_t) at->u[0].s64;
+		break;
+	case DW_FORM_data4:
+		*valp = (int32_t) at->u[0].s64;
+		break;
+	case DW_FORM_data8:
+	case DW_FORM_sdata:
+		*valp = at->u[0].s64;
+		break;
+	default:
+		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
+		return (DW_DLV_ERROR);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_attrval_unsigned(Dwarf_Die die, Dwarf_Half attr, Dwarf_Unsigned *valp, Dwarf_Error *err)
+{
+	Dwarf_Attribute at;
+	Dwarf_Die die1;
+	Dwarf_Unsigned val;
+	Dwarf_Debug dbg;
+	int first;
+
+	dbg = die != NULL ? die->die_dbg : NULL;
+
+	if (die == NULL || valp == NULL) {
+		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*valp = 0;
+
+	die1 = NULL;
+	for (;;) {
+		if ((at = _dwarf_attr_find(die, attr)) != NULL ||
+		    attr != DW_AT_type)
+			break;
+		if ((at = _dwarf_attr_find(die, DW_AT_abstract_origin)) ==
+		    NULL &&
+		    (at = _dwarf_attr_find(die, DW_AT_specification)) == NULL)
+			break;
+
+		switch (at->at_form) {
+		case DW_FORM_ref1:
+		case DW_FORM_ref2:
+		case DW_FORM_ref4:
+		case DW_FORM_ref8:
+		case DW_FORM_ref_udata:
+			val = at->u[0].u64;
+			first = (die1 == NULL);
+			die1 = _dwarf_die_find(die, val);
+			if (!first)
+				dwarf_dealloc(dbg, die, DW_DLA_DIE);
+			if (die1 == NULL) {
+				DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
+				return (DW_DLV_NO_ENTRY);
+			}
+			die = die1;
+			break;
+		default:
+			DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
+			return (DW_DLV_ERROR);
+		}
+	}
+
+	if (at == NULL) {
+		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	switch (at->at_form) {
+	case DW_FORM_addr:
+	case DW_FORM_data1:
+	case DW_FORM_data2:
+	case DW_FORM_data4:
+	case DW_FORM_data8:
+	case DW_FORM_udata:
+	case DW_FORM_ref1:
+	case DW_FORM_ref2:
+	case DW_FORM_ref4:
+	case DW_FORM_ref8:
+	case DW_FORM_ref_udata:
+		*valp = at->u[0].u64;
+		break;
+	default:
+		if (die1 != NULL)
+			dwarf_dealloc(dbg, die1, DW_DLA_DIE);
+		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
+		return (DW_DLV_ERROR);
+	}
+
+	if (die1 != NULL)
+		dwarf_dealloc(dbg, die1, DW_DLA_DIE);
+
+	return (DW_DLV_OK);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_attrval_signed.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,225 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_attrval_signed.3 3509 2016-12-29 03:58:41Z emaste $
+.\"
+.Dd December 26, 2016
+.Os
+.Dt DWARF_ATTRVAL_SIGNED 3
+.Sh NAME
+.Nm dwarf_attrval_flag ,
+.Nm dwarf_attrval_signed ,
+.Nm dwarf_attrval_string ,
+.Nm dwarf_attrval_unsigned
+.Nd retrieve the value of an attribute within a DWARF debugging information entry
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_attrval_flag
+.Fa "Dwarf_Die die"
+.Fa "Dwarf_Half attr"
+.Fa "Dwarf_Bool *ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_attrval_signed
+.Fa "Dwarf_Die die"
+.Fa "Dwarf_Half attr"
+.Fa "Dwarf_Signed *ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_attrval_string
+.Fa "Dwarf_Die die"
+.Fa "Dwarf_Half attr"
+.Fa "const char **ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_attrval_unsigned
+.Fa "Dwarf_Die die"
+.Fa "Dwarf_Half attr"
+.Fa "Dwarf_Unsigned *ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+These functions search the debugging information entry referenced
+by argument
+.Ar die
+for the attribute named by argument
+.Ar attr .
+If the named attribute is found, the functions set the location
+pointed to by argument
+.Ar ret
+to the value of the attribute.
+The argument
+.Ar err ,
+if non NULL,
+will be used to return an error descriptor in case of an error.
+.Pp
+Function
+.Fn dwarf_attrval_flag
+sets the location pointed to by argument
+.Ar ret
+to either 0 or 1. If the form of the attribute named by argument
+.Ar attr
+is
+.Dv DW_FORM_flag ,
+function
+.Fn dwarf_attrval_flag
+sets the location pointed to by argument
+.Ar ret
+to 1 if the attribute has a non-zero value, or to 0 otherwise.
+If the form of the attribute named by argument
+.Ar attr
+is
+.Dv DW_FORM_flag_present ,
+function
+.Fn dwarf_attrval_flag
+unconditionally sets the location pointed to by argument
+.Ar ret
+to 1.
+The form of the attribute must be one of
+.Dv DW_FORM_flag
+or
+.Dv DW_FORM_flag_present .
+.Pp
+Function
+.Fn dwarf_attrval_signed
+stores the value for the attribute named by argument
+.Ar attr ,
+into the location pointed to by argument
+.Ar ret .
+The attribute's value is treated as a signed integral quantity and is
+sign-extended as needed.
+The attribute named by the argument
+.Ar attr
+must belong to the
+.Dv CONSTANT
+class and must have one of the following forms:
+.Dv DW_FORM_data1 ,
+.Dv DW_FORM_data2 ,
+.Dv DW_FORM_data4 ,
+.Dv DW_FORM_data8
+or
+.Dv DW_FORM_sdata .
+.Pp
+Function
+.Fn dwarf_attrval_string
+sets the location pointed to by argument
+.Ar ret
+to a pointer to a NUL-terminated string that is the value of the
+attribute named by argument
+.Ar attr .
+The form of the attribute must be one of
+.Dv DW_FORM_string
+or
+.Dv DW_FORM_strp .
+.Pp
+Function
+.Fn dwarf_attrval_unsigned
+stores the value for the attribute named by argument
+.Ar attr
+into the location pointed to by argument
+.Ar ret .
+The attribute's value is treated as an unsigned integral quantity, and
+is zero-extended as needed.
+The named attribute must belong to one of the
+.Dv CONSTANT ,
+.Dv ADDRESS
+or
+.Dv REFERENCE
+classes and must have one of the following forms:
+.Dv DW_FORM_addr ,
+.Dv DW_FORM_data1 ,
+.Dv DW_FORM_data2 ,
+.Dv DW_FORM_data4 ,
+.Dv DW_FORM_data8 ,
+.Dv DW_FORM_udata ,
+.Dv DW_FORM_ref1 ,
+.Dv DW_FORM_ref2 ,
+.Dv DW_FORM_ref4 ,
+.Dv DW_FORM_ref8 ,
+or
+.Dv DW_FORM_ref_udata .
+.Pp
+If the attribute named by argument
+.Ar attr
+is
+.Dv DW_AT_type
+and is not present in the debugging information entry referenced by argument
+.Ar die ,
+and if a
+.Dv DW_AT_abstract_origin
+or
+.Dv DW_AT_specification
+attribute is present in the debugging information entry,
+function
+.Fn dwarf_attrval_unsigned
+will search for the named attribute in the debugging information entry
+referenced by the
+.Dv DW_AT_abstract_origin
+or
+.Dv DW_AT_specification
+attribute.
+.Sh RETURN VALUES
+On success, these functions returns
+.Dv DW_DLV_OK .
+If the named attribute was not found in the specified debugging
+information entry descriptor these functions return
+.Dv DW_DLV_NO_ENTRY
+and set argument
+.Ar err .
+For other errors, these functions return
+.Dv DW_DLV_ERROR
+and set argument
+.Ar err .
+.Sh COMPATIBILITY
+These functions are extensions added by this implementation of the
+DWARF(3) API.
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_ATTR_FORM_BAD"
+.It Bq Er DW_DLE_ARGUMENT
+Either of the arguments
+.Va die
+or
+.Va ret
+was NULL.
+.It Bq Er DW_DLE_NO_ENTRY
+Argument
+.Ar die
+did not contain an attribute corresponding to the value in argument
+.Ar attr .
+.It Bq Er DW_DLE_ATTR_FORM_BAD
+The attribute named by argument
+.Ar attr
+was not of a permitted form.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_attr 3 ,
+.Xr dwarf_hasattr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_child.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,278 @@
+.\" Copyright (c) 2010,2014 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_child.3 3127 2014-12-21 19:09:19Z jkoshy $
+.\"
+.Dd December 21, 2014
+.Os
+.Dt DWARF_CHILD 3
+.Sh NAME
+.Nm dwarf_child ,
+.Nm dwarf_offdie ,
+.Nm dwarf_offdie_b ,
+.Nm dwarf_siblingof ,
+.Nm dwarf_siblingof_b
+.Nd retrieve DWARF Debugging Information Entry descriptors
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fn dwarf_child "Dwarf_Die die" "Dwarf_Die *ret_die" "Dwarf_Error *err"
+.Ft int
+.Fo dwarf_offdie
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Off offset"
+.Fa "Dwarf_Die *ret_die"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_offdie_b
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Off offset"
+.Fa "Dwarf_Bool is_info"
+.Fa "Dwarf_Die *ret_die"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_siblingof
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Die die"
+.Fa "Dwarf_Die *ret_die"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_siblingof_b
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Die die"
+.Fa "Dwarf_Die *ret_die"
+.Fa "Dwarf_Bool is_info"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+These functions are used to retrieve and traverse DWARF
+Debugging Information Entry (DIE) descriptors associated with
+a compilation unit.
+These descriptors are arranged in the form of a tree, traversable
+using
+.Dq child
+and
+.Dq sibling
+links; see
+.Xr dwarf 3
+for more information.
+DWARF Debugging Information Entry descriptors are represented
+by the
+.Vt Dwarf_Die
+opaque type.
+.Pp
+Function
+.Fn dwarf_child
+retrieves the child of descriptor denoted by argument
+.Ar die ,
+and stores it in the location pointed to by argument
+.Ar ret_die .
+.Pp
+Function
+.Fn dwarf_siblingof
+retrieves the sibling of the descriptor denoted by argument
+.Ar die ,
+and stores it in the location pointed to by argument
+.Ar ret_die .
+If argument
+.Ar die
+is NULL, the first debugging information entry descriptor for the
+current compilation unit will be returned.
+This function and function
+.Fn dwarf_child
+may be used together to traverse the tree of debugging information
+entry descriptors for a compilation unit.
+.Pp
+Function
+.Fn dwarf_siblingof_b
+is identical to the function
+.Fn dwarf_siblingof
+except that it can retrieve the sibling descriptor from either the
+current compilation unit or type unit.
+If argument
+.Ar is_info
+is non-zero, the function behaves identically to function
+.Fn dwarf_siblingof .
+If argument
+.Ar is_info
+is zero, the descriptor referred by argument
+.Ar die
+should be associated with a debugging information entry in the
+type unit.
+The function will store the sibling of the descriptor in the location
+pointed to by argument
+.Ar ret_die .
+If argument
+.Ar is_info
+is zero and argument
+.Ar die
+is
+.Dv NULL ,
+the first debugging information entry descriptor for the
+current type unit will be returned.
+.Pp
+Function
+.Fn dwarf_offdie
+retrieves the debugging information entry descriptor at global offset
+.Ar offset
+in the
+.Dq .debug_info
+section of the object associated with argument
+.Ar dbg .
+The returned descriptor is written to the location pointed to by argument
+.Ar ret_die .
+.Pp
+Function
+.Fn dwarf_offdie_b
+is identical to the function
+.Fn dwarf_offdie
+except that it can retrieve the debugging information entry descriptor at
+global offset
+.Ar offset
+from either of the
+.Dq .debug_info
+and
+.Dq .debug_types
+sections of the object associated with argument
+.Ar dbg .
+If argument
+.Ar is_info
+is non-zero, the function will retrieve the debugging information
+entry from the
+.Dq .debug_info
+section, otherwise the function will retrieve the debugging
+information entry from the
+.Dq .debug_types
+section.
+The returned descriptor is written to the location pointed to by argument
+.Ar ret_die .
+.Ss Memory Management
+The memory area used for the
+.Vt Dwarf_Die
+descriptor returned in argument
+.Ar ret_die
+is allocated by the
+.Lb libdwarf .
+Application code should use function
+.Fn dwarf_dealloc
+with the allocation type
+.Dv DW_DLA_DIE
+to free the memory area when the
+.Vt Dwarf_Die
+descriptor is no longer needed.
+.Sh RETURN VALUES
+These functions return the following values:
+.Bl -tag -width ".Bq Er DW_DLV_NO_ENTRY"
+.It Bq Er DW_DLV_OK
+The call succeeded.
+.It Bq Er DW_DLV_ERROR
+The requested operation failed.
+Additional information about the error encountered will be recorded in
+argument
+.Ar err ,
+if it is not NULL.
+.It Bq Er DW_DLV_NO_ENTRY
+For functions
+.Fn dwarf_child ,
+.Fn dwarf_siblingof
+and
+.Fn dwarf_siblingof_b ,
+the descriptor denoted by argument
+.Ar die
+did not have a child or sibling.
+.Pp
+For functions
+.Fn dwarf_offdie
+and
+.Fn dwarf_offdie_b ,
+there was no debugging information entry at the offset specified by
+argument
+.Ar offset .
+.El
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_DIE_NO_CU_CONTEXT"
+.It Bq Er DW_DLE_ARGUMENT
+Arguments
+.Ar dbg ,
+.Ar die
+or
+.Ar ret_die
+were NULL.
+.It Bq Er DW_DLE_DIE_NO_CU_CONTEXT
+Argument
+.Ar dbg
+was not associated with a compilation unit.
+.It Bq Er DW_DLE_NO_ENTRY
+The descriptor denoted by argument
+.Ar die
+had no child or sibling, or there was no DWARF debugging information
+entry at the offset specified by argument
+.Va offset .
+.El
+.Sh EXAMPLES
+To retrieve the first DWARF Debugging Information Entry descriptor for
+the first compilation unit associated with a
+.Vt Dwarf_Debug
+instance, and to traverse all its children, use:
+.Bd -literal -offset indent
+Dwarf_Debug dbg;
+Dwarf_Die die, die0;
+Dwarf_Error de;
+
+\&... allocate dbg using dwarf_init() etc ...
+
+if (dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL, &de) !=
+    DW_DLV_OK)
+	errx(EXIT_FAILURE, "dwarf_next_cu_header: %s",
+	    dwarf_errmsg(de));
+
+/* Get the first DIE for the current compilation unit. */
+die = NULL;
+if (dwarf_siblingof(dbg, die, &die0, &de) != DW_DLV_OK)
+	errx(EXIT_FAILURE, "dwarf_siblingof: %s", dwarf_errmsg(de));
+
+/* Get the first child of this DIE. */
+die = die0;
+if (dwarf_child(die, &die0, &de) != DW_DLV_OK)
+	errx(EXIT_FAILURE, "dwarf_child: %s", dwarf_errmsg(de));
+
+/* Get the rest of children. */
+do {
+	die = die0;
+	if (dwarf_siblingof(dbg, die, &die0, &de) == DW_DLV_ERROR)
+		errx(EXIT_FAILURE, "dwarf_siblingof: %s",
+		    dwarf_errmsg(de));
+} while (die0 != NULL);
+.Ed
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_errmsg 3 ,
+.Xr dwarf_get_die_infotypes_flag.3 ,
+.Xr dwarf_next_cu_header 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_cu.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,161 @@
+/*-
+ * Copyright (c) 2007 John Birrell (jb@freebsd.org)
+ * Copyright (c) 2014 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_cu.c 3041 2014-05-18 15:11:03Z kaiwang27 $");
+
+int
+dwarf_next_cu_header_c(Dwarf_Debug dbg, Dwarf_Bool is_info,
+    Dwarf_Unsigned *cu_length, Dwarf_Half *cu_version,
+    Dwarf_Off *cu_abbrev_offset, Dwarf_Half *cu_pointer_size,
+    Dwarf_Half *cu_offset_size, Dwarf_Half *cu_extension_size,
+    Dwarf_Sig8 *type_signature, Dwarf_Unsigned *type_offset,
+    Dwarf_Unsigned *cu_next_offset, Dwarf_Error *error)
+{
+	Dwarf_CU cu;
+	int ret;
+
+	if (dbg == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (is_info) {
+		if (dbg->dbg_cu_current == NULL)
+			ret = _dwarf_info_first_cu(dbg, error);
+		else
+			ret = _dwarf_info_next_cu(dbg, error);
+	} else {
+		if (dbg->dbg_tu_current == NULL)
+			ret = _dwarf_info_first_tu(dbg, error);
+		else
+			ret = _dwarf_info_next_tu(dbg, error);
+	}
+
+	if (ret == DW_DLE_NO_ENTRY) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	} else if (ret != DW_DLE_NONE)
+		return (DW_DLV_ERROR);
+
+	if (is_info) {
+		if (dbg->dbg_cu_current == NULL) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+			return (DW_DLV_NO_ENTRY);
+		}
+		cu = dbg->dbg_cu_current;
+	} else {
+		if (dbg->dbg_tu_current == NULL) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+			return (DW_DLV_NO_ENTRY);
+		}
+		cu = dbg->dbg_tu_current;
+	}
+
+	if (cu_length)
+		*cu_length = cu->cu_length;
+	if (cu_version)
+		*cu_version = cu->cu_version;
+	if (cu_abbrev_offset)
+		*cu_abbrev_offset = (Dwarf_Off) cu->cu_abbrev_offset;
+	if (cu_pointer_size)
+		*cu_pointer_size = cu->cu_pointer_size;
+	if (cu_offset_size) {
+		if (cu->cu_length_size == 4)
+			*cu_offset_size = 4;
+		else
+			*cu_offset_size = 8;
+	}
+	if (cu_extension_size) {
+		if (cu->cu_length_size == 4)
+			*cu_extension_size = 0;
+		else
+			*cu_extension_size = 4;
+	}
+	if (cu_next_offset)
+		*cu_next_offset	= cu->cu_next_offset;
+
+	if (!is_info) {
+		if (type_signature)
+			*type_signature = cu->cu_type_sig;
+		if (type_offset)
+			*type_offset = cu->cu_type_offset;
+	}
+
+	return (DW_DLV_OK);
+}
+
+
+int
+dwarf_next_cu_header_b(Dwarf_Debug dbg, Dwarf_Unsigned *cu_length,
+    Dwarf_Half *cu_version, Dwarf_Off *cu_abbrev_offset,
+    Dwarf_Half *cu_pointer_size, Dwarf_Half *cu_offset_size,
+    Dwarf_Half *cu_extension_size, Dwarf_Unsigned *cu_next_offset,
+    Dwarf_Error *error)
+{
+
+	return (dwarf_next_cu_header_c(dbg, 1, cu_length, cu_version,
+	    cu_abbrev_offset, cu_pointer_size, cu_offset_size,
+	    cu_extension_size, NULL, NULL, cu_next_offset, error));
+}
+
+int
+dwarf_next_cu_header(Dwarf_Debug dbg, Dwarf_Unsigned *cu_length,
+    Dwarf_Half *cu_version, Dwarf_Off *cu_abbrev_offset,
+    Dwarf_Half *cu_pointer_size, Dwarf_Unsigned *cu_next_offset,
+    Dwarf_Error *error)
+{
+
+	return (dwarf_next_cu_header_b(dbg, cu_length, cu_version,
+	    cu_abbrev_offset, cu_pointer_size, NULL, NULL, cu_next_offset,
+	    error));
+}
+
+int
+dwarf_next_types_section(Dwarf_Debug dbg, Dwarf_Error *error)
+{
+
+	/* Free resource allocated for current .debug_types section. */
+	_dwarf_type_unit_cleanup(dbg);
+	dbg->dbg_types_loaded = 0;
+	dbg->dbg_types_off = 0;
+
+	/* Reset type unit pointer. */
+	dbg->dbg_tu_current = NULL;
+
+	/* Search for the next .debug_types section. */
+	dbg->dbg_types_sec = _dwarf_find_next_types_section(dbg,
+	    dbg->dbg_types_sec);
+
+	if (dbg->dbg_types_sec == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	return (DW_DLV_OK);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_dealloc.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,203 @@
+.\" Copyright (c) 2009-2011 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: dwarf_dealloc.3 2073 2011-10-27 03:30:47Z jkoshy $
+.\"
+.Dd July 23, 2011
+.Os
+.Dt DWARF_DEALLOC 3
+.Sh NAME
+.Nm dwarf_dealloc ,
+.Nm dwarf_fde_cie_list_dealloc ,
+.Nm dwarf_funcs_dealloc ,
+.Nm dwarf_globals_dealloc ,
+.Nm dwarf_pubtypes_dealloc ,
+.Nm dwarf_ranges_dealloc ,
+.Nm dwarf_srclines_dealloc ,
+.Nm dwarf_types_dealloc ,
+.Nm dwarf_vars_dealloc ,
+.Nm dwarf_weaks_dealloc
+.Nd release resources
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft void
+.Fo dwarf_dealloc
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Ptr ptr"
+.Fa "Dwarf_Unsigned type"
+.Fc
+.Fo dwarf_fde_cie_list_dealloc
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Cie *cie_list"
+.Fa "Dwarf_Signed cie_count"
+.Fa "Dwarf_Fde *fde_list"
+.Fa "Dwarf_Signed fde_count"
+.Fc
+.Ft void
+.Fo dwarf_funcs_dealloc
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Func *funcs"
+.Fa "Dwarf_Signed funccount"
+.Fc
+.Ft void
+.Fo dwarf_globals_dealloc
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Global *globals"
+.Fa "Dwarf_Signed globalcount"
+.Fc
+.Ft void
+.Fo dwarf_pubtypes_dealloc
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Type *pubtypes"
+.Fa "Dwarf_Signed pubtypecount"
+.Fc
+.Ft void
+.Fo dwarf_ranges_dealloc
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Ranges *ranges"
+.Fa "Dwarf_Signed rangecount"
+.Fc
+.Ft void
+.Fo dwarf_srclines_dealloc
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Line *lines"
+.Fa "Dwarf_Signed linecount"
+.Fc
+.Ft void
+.Fo dwarf_types_dealloc
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Type *types"
+.Fa "Dwarf_Signed typecount"
+.Fc
+.Ft void
+.Fo dwarf_vars_dealloc
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Var *vars"
+.Fa "Dwarf_Signed varcount"
+.Fc
+.Ft void
+.Fo dwarf_weaks_dealloc
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Weak *weaks"
+.Fa "Dwarf_Signed weakcount"
+.Fc
+.Sh DESCRIPTION
+The function
+.Fn dwarf_dealloc
+is used by applications to indicate that memory areas returned by
+.Lb libdwarf
+may be safely disposed off.
+Due to the way memory is managed in the current implementation, the
+use of
+.Fn dwarf_dealloc
+is only necessary for a small set of DWARF types.
+.Pp
+Argument
+.Ar dbg
+should reference a valid debugging context allocated using
+.Xr dwarf_init 3 .
+.Pp
+Argument
+.Ar ptr
+should point to an object or memory area obtained by a prior call
+to a DWARF(3) function.
+.Pp
+Argument
+.Ar type
+indicates the type of object being deallocated.
+The indicated type must match that of the object being passed in
+argument
+.Ar ptr .
+Valid values for the
+.Ar type
+argument are:
+.Bl -tag -width ".Dv DW_DLA_FRAME_BLOCK"
+.It Dv DW_DLA_ABBREV
+An object of type
+.Vt Dwarf_Abbrev ,
+as returned by a call to the function
+.Xr dwarf_get_abbrev 3 .
+.It Dv DW_DLA_DIE
+An object of type
+.Vt Dwarf_Die ,
+as returned by calls to the functions
+.Xr dwarf_child 3 ,
+.Xr dwarf_offdie 3
+or
+.Xr dwarf_siblingof 3 .
+.It Dv DW_DLA_FRAME_BLOCK
+An array of objects of type
+.Vt Dwarf_Frame_op ,
+as returned by a call to the function
+.Xr dwarf_expand_frame_instructions 3 .
+.El
+.Pp
+Calls to
+.Fn dwarf_dealloc
+with other values for argument
+.Ar type
+are no-ops in this implementation.
+.Pp
+The functions
+.Fn dwarf_fde_cie_list_dealloc ,
+.Fn dwarf_funcs_dealloc ,
+.Fn dwarf_globals_dealloc ,
+.Fn dwarf_pubtypes_dealloc ,
+.Fn dwarf_ranges_dealloc ,
+.Fn dwarf_srclines_dealloc ,
+.Fn dwarf_types_dealloc ,
+.Fn dwarf_vars_dealloc
+and
+.Fn dwarf_weaks_dealloc
+are provided for compatibility with other implementations of the
+DWARF(3) API.
+Due to the way memory is managed in the current implementation, these
+functions are effectively no-ops.
+.Pp
+See
+.Xr dwarf 3
+for more information about the memory management scheme in this
+implementation of the DWARF(3) API.
+.Sh RETURN VALUES
+Functions
+.Fn dwarf_dealloc ,
+.Fn dwarf_fde_cie_list_dealloc ,
+.Fn dwarf_funcs_dealloc ,
+.Fn dwarf_globals_dealloc ,
+.Fn dwarf_pubtypes_dealloc ,
+.Fn dwarf_ranges_dealloc ,
+.Fn dwarf_srclines_dealloc ,
+.Fn dwarf_types_dealloc ,
+.Fn dwarf_vars_dealloc
+and
+.Fn dwarf_weaks_dealloc
+have no return value.
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_child 3 ,
+.Xr dwarf_expand_frame_instructions 3 ,
+.Xr dwarf_get_abbrev 3 ,
+.Xr dwarf_offdie 3 ,
+.Xr dwarf_siblingof 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_dealloc.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,117 @@
+/*-
+ * Copyright (c) 2007 John Birrell (jb@freebsd.org)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_dealloc.c 2073 2011-10-27 03:30:47Z jkoshy $");
+
+void
+dwarf_dealloc(Dwarf_Debug dbg, Dwarf_Ptr p, Dwarf_Unsigned alloc_type)
+{
+	Dwarf_Abbrev ab;
+	Dwarf_AttrDef ad, tad;
+	Dwarf_Attribute at, tat;
+	Dwarf_Die die;
+
+	/*
+	 * This libdwarf implementation does not use the SGI/libdwarf
+	 * style of memory allocation. In most cases it does not copy
+	 * things to return to the client, so the client does not need
+	 * to remember to free them.  The remaining cases are handled
+	 * below.
+	 */
+
+	(void) dbg;
+
+	if (alloc_type == DW_DLA_LIST || alloc_type == DW_DLA_FRAME_BLOCK ||
+	    alloc_type == DW_DLA_LOC_BLOCK || alloc_type == DW_DLA_LOCDESC)
+		free(p);
+	else if (alloc_type == DW_DLA_ABBREV) {
+		ab = p;
+		STAILQ_FOREACH_SAFE(ad, &ab->ab_attrdef, ad_next, tad) {
+			STAILQ_REMOVE(&ab->ab_attrdef, ad, _Dwarf_AttrDef,
+			    ad_next);
+			free(ad);
+		}
+		free(ab);
+	} else if (alloc_type == DW_DLA_DIE) {
+		die = p;
+		STAILQ_FOREACH_SAFE(at, &die->die_attr, at_next, tat) {
+			STAILQ_REMOVE(&die->die_attr, at,
+			    _Dwarf_Attribute, at_next);
+			if (at->at_ld != NULL)
+				free(at->at_ld);
+			free(at);
+		}
+		if (die->die_attrarray)
+			free(die->die_attrarray);
+		free(die);
+	}
+}
+
+void
+dwarf_srclines_dealloc(Dwarf_Debug dbg, Dwarf_Line *linebuf,
+	Dwarf_Signed count)
+{
+	/*
+	 * In this libdwarf implementation, line information remains
+	 * associated with the DIE for a compilation unit for the
+	 * lifetime of the DIE.  The client does not need to free
+	 * the memory returned by `dwarf_srclines()`.
+	 */ 
+
+	(void) dbg; (void) linebuf; (void) count;
+}
+
+void
+dwarf_ranges_dealloc(Dwarf_Debug dbg, Dwarf_Ranges *ranges,
+    Dwarf_Signed range_count)
+{
+	/*
+	 * In this libdwarf implementation, ranges information is
+	 * kept by a STAILQ inside Dwarf_Debug object. The client
+	 * does not need to free the memory returned by
+	 * `dwarf_get_ranges()` or `dwarf_get_ranges_a()`.
+	 */
+
+	(void) dbg; (void) ranges; (void) range_count;
+}
+
+void
+dwarf_fde_cie_list_dealloc(Dwarf_Debug dbg, Dwarf_Cie *cie_list,
+    Dwarf_Signed cie_count, Dwarf_Fde *fde_list, Dwarf_Signed fde_count)
+{
+	/*
+	 * In this implementation, FDE and CIE information is managed
+	 * as part of the Dwarf_Debug object.  The client does not need
+	 * to explicitly free these memory arenas.
+	 */
+	(void) dbg;
+	(void) cie_list;
+	(void) cie_count;
+	(void) fde_list;
+	(void) fde_count;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_def_macro.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,129 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_def_macro.3 3182 2015-04-10 16:08:10Z emaste $
+.\"
+.Dd November 9, 2011
+.Os
+.Dt DWARF_DEF_MACRO 3
+.Sh NAME
+.Nm dwarf_def_macro
+.Nd add a macro definition to a DWARF producer instance
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "int"
+.Fo dwarf_def_macro
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_Unsigned lineno"
+.Fa "char *name"
+.Fa "char *value"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_def_macro
+adds a macro definition to a DWARF producer instance.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar lineno
+specifies the line number of the source line where the macro is
+defined.
+A line number of zero is used for macros that are defined
+before any source file is read.
+.Pp
+Argument
+.Ar name
+should point to a NUL-terminated string containing the name
+of the macro.
+For function-like macros this parameter should also include
+parentheses and parameter names if any.
+.Pp
+Argument
+.Ar value
+should point to a NUL-terminated string containing the value
+of the macro.
+If the macro does not have a value, argument
+.Ar value
+should be set to NULL.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_def_macro
+returns
+.Dv DW_DLV_OK .
+In case of an error, function
+.Fn dwarf_def_macro
+returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh EXAMPLE
+To record the fact that a macro named
+.Dv _STDIO_H_
+was defined at line 20 of the current macro file, use:
+.Bd -literal -offset indent
+Dwarf_P_Debug dbg;
+Dwarf_Error de;
+
+/* ... Assume 'dbg' refers to a DWARF producer instance... */
+if (dwarf_def_macro(dbg, 20, "_STDIO_H_", NULL, &de) != DW_DLV_OK)
+	errx(EXIT_FAILURE, "dwarf_def_macro failed: %s",
+	    dwarf_errmsg(-1));
+.Ed
+.Sh ERRORS
+Function
+.Fn dwarf_def_macro
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Either arguments
+.Ar dbg
+or
+.Ar name
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_end_macro_file 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3 ,
+.Xr dwarf_start_macro_file 3 ,
+.Xr dwarf_undef_macro 3 ,
+.Xr dwarf_vendor_ext 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_die.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,413 @@
+/*-
+ * Copyright (c) 2007 John Birrell (jb@freebsd.org)
+ * Copyright (c) 2009,2011,2014 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_die.c 3039 2014-05-18 15:10:56Z kaiwang27 $");
+
+int
+dwarf_child(Dwarf_Die die, Dwarf_Die *ret_die, Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+	Dwarf_Section *ds;
+	Dwarf_CU cu;
+	int ret;
+
+	dbg = die != NULL ? die->die_dbg : NULL;
+
+	if (die == NULL || ret_die == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (die->die_ab->ab_children == DW_CHILDREN_no)
+		return (DW_DLV_NO_ENTRY);
+
+	dbg = die->die_dbg;
+	cu = die->die_cu;
+	ds = cu->cu_is_info ? dbg->dbg_info_sec : dbg->dbg_types_sec;
+	ret = _dwarf_die_parse(die->die_dbg, ds, cu, cu->cu_dwarf_size,
+	    die->die_next_off, cu->cu_next_offset, ret_die, 0, error);
+
+	if (ret == DW_DLE_NO_ENTRY) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	} else if (ret != DW_DLE_NONE)
+		return (DW_DLV_ERROR);
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_siblingof_b(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Die *ret_die,
+    Dwarf_Bool is_info, Dwarf_Error *error)
+{
+	Dwarf_CU cu;
+	Dwarf_Attribute at;
+	Dwarf_Section *ds;
+	uint64_t offset;
+	int ret, search_sibling;
+
+	if (dbg == NULL || ret_die == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	ds = is_info ? dbg->dbg_info_sec : dbg->dbg_types_sec;
+	cu = is_info ? dbg->dbg_cu_current : dbg->dbg_tu_current;
+
+	if (cu == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_DIE_NO_CU_CONTEXT);
+		return (DW_DLV_ERROR);
+	}
+
+	/* Application requests the first DIE in this CU. */
+	if (die == NULL)
+		return (dwarf_offdie_b(dbg, cu->cu_1st_offset, is_info,
+		    ret_die, error));
+
+	/*
+	 * Check if the `is_info' flag matches the debug section the
+	 * DIE belongs to.
+	 */
+	if (is_info != die->die_cu->cu_is_info) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	/*
+	 * If the DIE doesn't have any children, its sibling sits next
+	 * right to it.
+	 */
+	search_sibling = 0;
+	if (die->die_ab->ab_children == DW_CHILDREN_no)
+		offset = die->die_next_off;
+	else {
+		/*
+		 * Look for DW_AT_sibling attribute for the offset of
+		 * its sibling.
+		 */
+		if ((at = _dwarf_attr_find(die, DW_AT_sibling)) != NULL) {
+			if (at->at_form != DW_FORM_ref_addr)
+				offset = at->u[0].u64 + cu->cu_offset;
+			else
+				offset = at->u[0].u64;
+		} else {
+			offset = die->die_next_off;
+			search_sibling = 1;
+		}
+	}
+
+	ret = _dwarf_die_parse(die->die_dbg, ds, cu, cu->cu_dwarf_size, offset,
+	    cu->cu_next_offset, ret_die, search_sibling, error);
+	
+	if (ret == DW_DLE_NO_ENTRY) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	} else if (ret != DW_DLE_NONE)
+		return (DW_DLV_ERROR);
+
+	return (DW_DLV_OK);
+}
+
+
+int
+dwarf_siblingof(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Die *ret_die,
+    Dwarf_Error *error)
+{
+
+	return (dwarf_siblingof_b(dbg, die, ret_die, 1, error));
+}
+
+static int
+_dwarf_search_die_within_cu(Dwarf_Debug dbg, Dwarf_Section *s, Dwarf_CU cu,
+    Dwarf_Off offset, Dwarf_Die *ret_die, Dwarf_Error *error)
+{
+
+	assert(dbg != NULL && cu != NULL && ret_die != NULL);
+
+	return (_dwarf_die_parse(dbg, s, cu, cu->cu_dwarf_size,
+	    offset, cu->cu_next_offset, ret_die, 0, error));
+}
+
+int
+dwarf_offdie_b(Dwarf_Debug dbg, Dwarf_Off offset, Dwarf_Bool is_info,
+    Dwarf_Die *ret_die, Dwarf_Error *error)
+{
+	Dwarf_Section *ds;
+	Dwarf_CU cu;
+	int ret;
+
+	if (dbg == NULL || ret_die == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	ds = is_info ? dbg->dbg_info_sec : dbg->dbg_types_sec;
+	cu = is_info ? dbg->dbg_cu_current : dbg->dbg_tu_current;
+
+	/* First search the current CU. */
+	if (cu != NULL) {
+		if (offset > cu->cu_offset && offset < cu->cu_next_offset) {
+			ret = _dwarf_search_die_within_cu(dbg, ds, cu, offset,
+			    ret_die, error);
+			if (ret == DW_DLE_NO_ENTRY) {
+				DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+				return (DW_DLV_NO_ENTRY);
+			} else if (ret != DW_DLE_NONE)
+				return (DW_DLV_ERROR);
+			return (DW_DLV_OK);
+		}
+	}
+
+	/* Search other CUs. */
+	ret = _dwarf_info_load(dbg, 1, is_info, error);
+	if (ret != DW_DLE_NONE)
+		return (DW_DLV_ERROR);
+
+	if (is_info) {
+		STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {
+			if (offset < cu->cu_offset ||
+			    offset > cu->cu_next_offset)
+				continue;
+			ret = _dwarf_search_die_within_cu(dbg, ds, cu, offset,
+			    ret_die, error);
+			if (ret == DW_DLE_NO_ENTRY) {
+				DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+				return (DW_DLV_NO_ENTRY);
+			} else if (ret != DW_DLE_NONE)
+				return (DW_DLV_ERROR);
+			return (DW_DLV_OK);
+		}
+	} else {
+		STAILQ_FOREACH(cu, &dbg->dbg_tu, cu_next) {
+			if (offset < cu->cu_offset ||
+			    offset > cu->cu_next_offset)
+				continue;
+			ret = _dwarf_search_die_within_cu(dbg, ds, cu, offset,
+			    ret_die, error);
+			if (ret == DW_DLE_NO_ENTRY) {
+				DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+				return (DW_DLV_NO_ENTRY);
+			} else if (ret != DW_DLE_NONE)
+				return (DW_DLV_ERROR);
+			return (DW_DLV_OK);
+		}
+	}
+
+	DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+	return (DW_DLV_NO_ENTRY);
+}
+
+int
+dwarf_offdie(Dwarf_Debug dbg, Dwarf_Off offset, Dwarf_Die *ret_die,
+    Dwarf_Error *error)
+{
+
+	return (dwarf_offdie_b(dbg, offset, 1, ret_die, error));
+}
+
+int
+dwarf_tag(Dwarf_Die die, Dwarf_Half *tag, Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+
+	dbg = die != NULL ? die->die_dbg : NULL;
+
+	if (die == NULL || tag == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	assert(die->die_ab != NULL);
+
+	*tag = (Dwarf_Half) die->die_ab->ab_tag;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_dieoffset(Dwarf_Die die, Dwarf_Off *ret_offset, Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+
+	dbg = die != NULL ? die->die_dbg : NULL;
+
+	if (die == NULL || ret_offset == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*ret_offset = die->die_offset;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_die_CU_offset(Dwarf_Die die, Dwarf_Off *ret_offset, Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+	Dwarf_CU cu;
+
+	dbg = die != NULL ? die->die_dbg : NULL;
+
+	if (die == NULL || ret_offset == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	cu = die->die_cu;
+	assert(cu != NULL);
+
+	*ret_offset = die->die_offset - cu->cu_offset;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_die_CU_offset_range(Dwarf_Die die, Dwarf_Off *cu_offset,
+    Dwarf_Off *cu_length, Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+	Dwarf_CU cu;
+
+	dbg = die != NULL ? die->die_dbg : NULL;
+
+	if (die == NULL || cu_offset == NULL || cu_length == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	cu = die->die_cu;
+	assert(cu != NULL);
+
+	*cu_offset = cu->cu_offset;
+	*cu_length = cu->cu_length + cu->cu_length_size;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_diename(Dwarf_Die die, char **ret_name, Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+
+	dbg = die != NULL ? die->die_dbg : NULL;
+
+	if (die == NULL || ret_name == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (die->die_name == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	*ret_name = die->die_name;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_die_abbrev_code(Dwarf_Die die)
+{
+
+	assert(die != NULL);
+
+	return (die->die_abnum);
+}
+
+int
+dwarf_get_cu_die_offset_given_cu_header_offset_b(Dwarf_Debug dbg,
+    Dwarf_Off in_cu_header_offset, Dwarf_Bool is_info,
+    Dwarf_Off *out_cu_die_offset, Dwarf_Error *error)
+{
+	Dwarf_CU cu;
+
+	if (dbg == NULL || out_cu_die_offset == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (is_info) {
+		STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {
+			if (cu->cu_offset == in_cu_header_offset) {
+				*out_cu_die_offset = cu->cu_1st_offset;
+				break;
+			}
+		}
+	} else {
+		STAILQ_FOREACH(cu, &dbg->dbg_tu, cu_next) {
+			if (cu->cu_offset == in_cu_header_offset) {
+				*out_cu_die_offset = cu->cu_1st_offset;
+				break;
+			}
+		}
+	}
+
+	if (cu == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_cu_die_offset_given_cu_header_offset(Dwarf_Debug dbg,
+    Dwarf_Off in_cu_header_offset, Dwarf_Off *out_cu_die_offset,
+    Dwarf_Error *error)
+{
+
+	return (dwarf_get_cu_die_offset_given_cu_header_offset_b(dbg,
+	    in_cu_header_offset, 1, out_cu_die_offset, error));
+}
+
+int
+dwarf_get_address_size(Dwarf_Debug dbg, Dwarf_Half *addr_size,
+    Dwarf_Error *error)
+{
+
+	if (dbg == NULL || addr_size == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*addr_size = dbg->dbg_pointer_size;
+
+	return (DW_DLV_OK);
+}
+
+Dwarf_Bool
+dwarf_get_die_infotypes_flag(Dwarf_Die die)
+{
+
+	assert(die != NULL);
+
+	return (die->die_cu->cu_is_info);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_die_abbrev_code.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,55 @@
+.\" Copyright (c) 2010 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_die_abbrev_code.3 2073 2011-10-27 03:30:47Z jkoshy $
+.\"
+.Dd April 14, 2010
+.Os
+.Dt DWARF_DIE_ABBREV_CODE 3
+.Sh NAME
+.Nm dwarf_die_abbrev_code
+.Nd retrieve the abbreviation code for a DWARF debugging information entry
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fn dwarf_die_abbrev_code "Dwarf_Die die"
+.Sh DESCRIPTION
+Function
+.Fn dwarf_die_abbrev_code
+returns the abbreviation code for the debugging information entry descriptor
+referenced by argument
+.Ar die .
+Argument
+.Ar die
+should be a valid pointer to a value of type
+.Vt Dwarf_Die .
+.Sh RETURN VALUES
+The function returns an integral value.
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_diename 3 ,
+.Xr dwarf_dieoffset 3 ,
+.Xr dwarf_tag 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_die_link.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,118 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_die_link.3 2073 2011-10-27 03:30:47Z jkoshy $
+.\"
+.Dd September 4, 2011
+.Os
+.Dt DWARF_DIE_LINK 3
+.Sh NAME
+.Nm dwarf_die_link
+.Nd link a debugging information entry
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft Dwarf_P_Die
+.Fo dwarf_die_link
+.Fa "Dwarf_P_Die die"
+.Fa "Dwarf_P_Die parent"
+.Fa "Dwarf_P_Die child"
+.Fa "Dwarf_P_Die left"
+.Fa "Dwarf_P_Die right"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_die_link
+links debugging information entries together.
+.Pp
+Argument
+.Ar die
+should specify the debugging information entry to be updated.
+.Pp
+Argument
+.Ar parent
+specifies the new parent link for the debugging information entry.
+.Pp
+Argument
+.Ar child
+specifies the new first child link for the debugging information entry.
+.Pp
+Argument
+.Ar left
+specifies the new left sibling link for the debugging information entry.
+.Pp
+Argument
+.Ar right
+specifies the new right sibling link for the debugging information entry.
+.Pp
+Only one of arguments
+.Ar parent ,
+.Ar child ,
+.Ar left
+and
+.Ar right
+is allowed to be non-NULL.
+Existing links to parent, child, left or right debugging information
+entries, if any, will be unlinked before the specified link is
+established.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_die_link
+returns the debugging information entry provided in argument
+.Ar die .
+In case of an error, function
+.Fn dwarf_die_link
+returns
+.Dv DW_DLV_BADADDR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+The function
+.Fn dwarf_die_link
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Ar die
+was NULL.
+.It Bq Er DW_DLE_ARGUMENT
+More than one of the arguments
+.Ar parent ,
+.Ar child ,
+.Ar left
+and
+.Ar right
+were non-NULL.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_die_to_debug 3 ,
+.Xr dwarf_new_die 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_diename.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,90 @@
+.\" Copyright (c) 2010 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_diename.3 2073 2011-10-27 03:30:47Z jkoshy $
+.\"
+.Dd March 31, 2010
+.Os
+.Dt DWARF_DIENAME 3
+.Sh NAME
+.Nm dwarf_diename
+.Nd retrieve the name associated with a debugging information entry
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fn dwarf_diename "Dwarf_Die die" "char **ret_name" "Dwarf_Error *err"
+.Sh DESCRIPTION
+Function
+.Fn dwarf_diename
+retrieves a pointer to the NUL-terminated string associated with the
+.Dv DW_AT_name
+attribute of the debugging information entry descriptor referenced by
+argument
+.Ar die .
+If the pointer was successfully retrieved, it is stored in the location
+pointed to by argument
+.Ar ret_name .
+.Sh RETURN VALUES
+Function
+.Fn dwarf_diename
+returns
+.Dv DW_DLV_OK on success.
+.Pp
+If the debugging information entry descriptor denoted by argument
+.Ar die
+does not contain a
+.Dv DW_AT_name
+attribute, the function returns
+.Dv DW_DLV_NO_ENTRY
+and sets argument
+.Ar err .
+For other errors, it returns
+.Dv DW_DLV_ERROR
+and sets argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_diename
+can fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Either of arguments
+.Ar die
+or
+.Ar ret_name
+was NULL.
+.It Bq Er DW_DLE_NO_ENTRY
+Argument
+.Ar die
+had no
+.Dv DW_AT_name
+attribute.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_tag 3 ,
+.Xr dwarf_dieoffset 3 ,
+.Xr dwarf_die_abbrev_code 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_dieoffset.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,206 @@
+.\" Copyright (c) 2010,2014 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_dieoffset.3 3129 2014-12-21 20:06:26Z jkoshy $
+.\"
+.Dd December 21, 2014
+.Os
+.Dt DWARF_DIEOFFSET 3
+.Sh NAME
+.Nm dwarf_die_CU_offset ,
+.Nm dwarf_die_CU_offset_range ,
+.Nm dwarf_dieoffset ,
+.Nm dwarf_get_cu_die_offset_given_cu_header_offset ,
+.Nm dwarf_get_cu_die_offset_given_cu_header_offset_b
+.Nd return offsets of DWARF debugging information entries
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_die_CU_offset
+.Fa "Dwarf_Die die"
+.Fa "Dwarf_Off *ret_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_die_CU_offset_range
+.Fa "Dwarf_Die die"
+.Fa "Dwarf_Off *cu_offset"
+.Fa "Dwarf_Off *cu_length"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_dieoffset
+.Fa "Dwarf_Die die"
+.Fa "Dwarf_Off *ret_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_get_cu_die_offset_given_cu_header_offset
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Off in_cu_header_offset"
+.Fa "Dwarf_Off *out_cu_die_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_get_cu_die_offset_given_cu_header_offset_b
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Off in_cu_header_offset"
+.Fa "Dwarf_Bool is_info"
+.Fa "Dwarf_Off *out_cu_die_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+These functions are used to retrieve offsets for DWARF debugging
+information entries.
+.Pp
+Function
+.Fn dwarf_die_CU_offset
+returns the offset of the debugging information entry referenced by
+argument
+.Ar die
+relative to the start of its containing compilation unit.
+Argument
+.Ar ret_offset
+should point to the location that is to hold the returned offset.
+If argument
+.Ar err
+is non-NULL, it will be used to return an error descriptor in case of
+an error.
+.Pp
+Function
+.Fn dwarf_die_CU_offset_range
+returns the section-relative offset and length of the compilation unit
+containing the debugging information entry referenced by argument
+.Ar die .
+Argument
+.Ar cu_offset
+should point to a location that will hold the returned offset.
+Argument
+.Ar cu_length
+should point to a location that will hold the returned length of the
+compilation unit.
+If argument
+.Ar err
+is non-NULL, it will be used to return an error descriptor in case of
+an error.
+.Pp
+Function
+.Fn dwarf_dieoffset
+retrieves the section-relative offset of the debugging information
+entry referenced by argument
+.Ar die .
+Argument
+.Ar ret_offset
+should point to a location that is to hold the returned
+section-relative offset.
+If argument
+.Ar err
+is non-NULL, it will be used to return an error descriptor in case of
+an error.
+.Pp
+Function
+.Fn dwarf_get_cu_die_offset_given_cu_header_offset
+returns the offset for the first debugging information entry for a
+compilation unit, given an offset to the header of the compilation
+unit.
+Argument
+.Ar dbg
+should reference a valid debugging context allocated using
+.Xr dwarf_init 3 .
+Argument
+.Ar in_cu_header_offset
+contains the offset to the start of a compilation unit.
+Argument
+.Ar out_cu_die_offset
+points to a location that will hold the returned offset.
+If argument
+.Ar err
+is non-NULL, it will be used to return an error descriptor in case of
+an error.
+.Pp
+Function
+.Fn dwarf_get_cu_die_offset_given_cu_header_offset_b
+behaves identically to the function
+.Fn dwarf_get_cu_die_offset_given_cu_header_offset
+when the argument
+.Ar is_info
+is non-zero.
+When the argument
+.Ar is_info
+is zero, function
+.Fn dwarf_get_cu_die_offset_given_cu_header_offset_b
+returns the offset for the first debugging information entry for a
+type unit, given an offset to the header of the type unit in argument
+.Ar in_cu_header_offset .
+Argument
+.Ar out_cu_die_offset
+points to a location that will hold the returned offset.
+If the argument
+.Ar err
+is non-NULL, it will be used to return an error descriptor in case of
+an error.
+.Sh RETURN VALUES
+On success, these functions return
+.Dv DW_DLV_OK .
+In case of an error, these functions return
+.Dv DW_DLV_ERROR
+and set argument
+.Ar err .
+.Pp
+Function
+.Fn dwarf_get_cu_die_offset_given_cu_header_offset
+and
+.Fn dwarf_get_cu_die_offset_given_cu_header_offset_b
+returns
+.Dv DW_DLV_NO_ENTRY
+and sets argument
+.Ar err
+if there is no compilation or type unit located at the
+offset specified in argument
+.Ar in_cu_header_offset .
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Va cu_length ,
+.Va cu_offset ,
+.Va dbg ,
+.Va die ,
+.Va out_cu_die_offset
+or
+.Va ret_offset
+was NULL.
+.It Bq Er DW_DLE_NO_ENTRY
+Argument
+.Ar in_cu_header_offset
+specified an unknown offset.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_next_cu_header 3 ,
+.Xr dwarf_offdie 3 ,
+.Xr dwarf_offdie_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_dump.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,1482 @@
+/*-
+ * Copyright (c) 2007 John Birrell (jb@freebsd.org)
+ * Copyright (c) 2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_dump.c 3494 2016-09-20 17:16:13Z emaste $");
+
+int
+dwarf_get_ACCESS_name(unsigned access, const char **s)
+{
+
+	assert(s != NULL);
+
+	switch (access) {
+	case DW_ACCESS_public:
+		*s = "DW_ACCESS_public"; break;
+	case DW_ACCESS_protected:
+		*s = "DW_ACCESS_protected"; break;
+	case DW_ACCESS_private:
+		*s = "DW_ACCESS_private"; break;
+	default:
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_AT_name(unsigned attr, const char **s)
+{
+
+	assert(s != NULL);
+
+	switch (attr) {
+	case DW_AT_abstract_origin:
+		*s = "DW_AT_abstract_origin"; break;
+	case DW_AT_accessibility:
+		*s = "DW_AT_accessibility"; break;
+	case DW_AT_address_class:
+		*s = "DW_AT_address_class"; break;
+	case DW_AT_artificial:
+		*s = "DW_AT_artificial"; break;
+	case DW_AT_allocated:
+		*s = "DW_AT_allocated"; break;
+	case DW_AT_associated:
+		*s = "DW_AT_associated"; break;
+	case DW_AT_base_types:
+		*s = "DW_AT_base_types"; break;
+	case DW_AT_binary_scale:
+		*s = "DW_AT_binary_scale"; break;
+	case DW_AT_bit_offset:
+		*s = "DW_AT_bit_offset"; break;
+	case DW_AT_bit_size:
+		*s = "DW_AT_bit_size"; break;
+	case DW_AT_bit_stride:
+		*s = "DW_AT_bit_stride"; break;
+	case DW_AT_byte_size:
+		*s = "DW_AT_byte_size"; break;
+	case DW_AT_byte_stride:
+		*s = "DW_AT_byte_stride"; break;
+	case DW_AT_calling_convention:
+		*s = "DW_AT_calling_convention"; break;
+	case DW_AT_common_reference:
+		*s = "DW_AT_common_reference"; break;
+	case DW_AT_comp_dir:
+		*s = "DW_AT_comp_dir"; break;
+	case DW_AT_const_expr:
+		*s = "DW_AT_const_expr"; break;
+	case DW_AT_const_value:
+		*s = "DW_AT_const_value"; break;
+	case DW_AT_containing_type:
+		*s = "DW_AT_containing_type"; break;
+	case DW_AT_count:
+		*s = "DW_AT_count"; break;
+	case DW_AT_call_column:
+		*s = "DW_AT_call_column"; break;
+	case DW_AT_call_file:
+		*s = "DW_AT_call_file"; break;
+	case DW_AT_call_line:
+		*s = "DW_AT_call_line"; break;
+	case DW_AT_data_bit_offset:
+		*s = "DW_AT_data_bit_offset"; break;
+	case DW_AT_data_location:
+		*s = "DW_AT_data_location"; break;
+	case DW_AT_data_member_location:
+		*s = "DW_AT_data_member_location"; break;
+	case DW_AT_decl_column:
+		*s = "DW_AT_decl_column"; break;
+	case DW_AT_decl_file:
+		*s = "DW_AT_decl_file"; break;
+	case DW_AT_decl_line:
+		*s = "DW_AT_decl_line"; break;
+	case DW_AT_declaration:
+		*s = "DW_AT_declaration"; break;
+	case DW_AT_default_value:
+		*s = "DW_AT_default_value"; break;
+	case DW_AT_decimal_scale:
+		*s = "DW_AT_decimal_scale"; break;
+	case DW_AT_decimal_sign:
+		*s = "DW_AT_decimal_sign"; break;
+	case DW_AT_description:
+		*s = "DW_AT_description"; break;
+	case DW_AT_digit_count:
+		*s = "DW_AT_digit_count"; break;
+	case DW_AT_discr:
+		*s = "DW_AT_discr"; break;
+	case DW_AT_discr_list:
+		*s = "DW_AT_discr_list"; break;
+	case DW_AT_discr_value:
+		*s = "DW_AT_discr_value"; break;
+	case DW_AT_element_list:
+		*s = "DW_AT_element_list"; break;
+	case DW_AT_encoding:
+		*s = "DW_AT_encoding"; break;
+	case DW_AT_enum_class:
+		*s = "DW_AT_enum_class"; break;
+	case DW_AT_external:
+		*s = "DW_AT_external"; break;
+	case DW_AT_entry_pc:
+		*s = "DW_AT_entry_pc"; break;
+	case DW_AT_extension:
+		*s = "DW_AT_extension"; break;
+	case DW_AT_explicit:
+		*s = "DW_AT_explicit"; break;
+	case DW_AT_endianity:
+		*s = "DW_AT_endianity"; break;
+	case DW_AT_elemental:
+		*s = "DW_AT_elemental"; break;
+	case DW_AT_frame_base:
+		*s = "DW_AT_frame_base"; break;
+	case DW_AT_friend:
+		*s = "DW_AT_friend"; break;
+	case DW_AT_high_pc:
+		*s = "DW_AT_high_pc"; break;
+	case DW_AT_hi_user:
+		*s = "DW_AT_hi_user"; break;
+	case DW_AT_identifier_case:
+		*s = "DW_AT_identifier_case"; break;
+	case DW_AT_import:
+		*s = "DW_AT_import"; break;
+	case DW_AT_inline:
+		*s = "DW_AT_inline"; break;
+	case DW_AT_is_optional:
+		*s = "DW_AT_is_optional"; break;
+	case DW_AT_language:
+		*s = "DW_AT_language"; break;
+	case DW_AT_linkage_name:
+		*s = "DW_AT_linkage_name"; break;
+	case DW_AT_lo_user:
+		*s = "DW_AT_lo_user"; break;
+	case DW_AT_location:
+		*s = "DW_AT_location"; break;
+	case DW_AT_low_pc:
+		*s = "DW_AT_low_pc"; break;
+	case DW_AT_lower_bound:
+		*s = "DW_AT_lower_bound"; break;
+	case DW_AT_macro_info:
+		*s = "DW_AT_macro_info"; break;
+	case DW_AT_main_subprogram:
+		*s = "DW_AT_main_subprogram"; break;
+	case DW_AT_mutable:
+		*s = "DW_AT_mutable"; break;
+	case DW_AT_member:
+		*s = "DW_AT_member"; break;
+	case DW_AT_name:
+		*s = "DW_AT_name"; break;
+	case DW_AT_namelist_item:
+		*s = "DW_AT_namelist_item"; break;
+	case DW_AT_ordering:
+		*s = "DW_AT_ordering"; break;
+	case DW_AT_object_pointer:
+		*s = "DW_AT_object_pointer"; break;
+	case DW_AT_priority:
+		*s = "DW_AT_priority"; break;
+	case DW_AT_producer:
+		*s = "DW_AT_producer"; break;
+	case DW_AT_prototyped:
+		*s = "DW_AT_prototyped"; break;
+	case DW_AT_picture_string:
+		*s = "DW_AT_picture_string"; break;
+	case DW_AT_pure:
+		*s = "DW_AT_pure"; break;
+	case DW_AT_return_addr:
+		*s = "DW_AT_return_addr"; break;
+	case DW_AT_ranges:
+		*s = "DW_AT_ranges"; break;
+	case DW_AT_recursive:
+		*s = "DW_AT_recursive"; break;
+	case DW_AT_segment:
+		*s = "DW_AT_segment"; break;
+	case DW_AT_sibling:
+		*s = "DW_AT_sibling"; break;
+	case DW_AT_signature:
+		*s = "DW_AT_signature"; break;
+	case DW_AT_specification:
+		*s = "DW_AT_specification"; break;
+	case DW_AT_start_scope:
+		*s = "DW_AT_start_scope"; break;
+	case DW_AT_static_link:
+		*s = "DW_AT_static_link"; break;
+	case DW_AT_stmt_list:
+		*s = "DW_AT_stmt_list"; break;
+	case DW_AT_string_length:
+		*s = "DW_AT_string_length"; break;
+	case DW_AT_subscr_data:
+		*s = "DW_AT_subscr_data"; break;
+	case DW_AT_small:
+		*s = "DW_AT_small"; break;
+	case DW_AT_type:
+		*s = "DW_AT_type"; break;
+	case DW_AT_trampoline:
+		*s = "DW_AT_trampoline"; break;
+	case DW_AT_threads_scaled:
+		*s = "DW_AT_threads_scaled"; break;
+	case DW_AT_upper_bound:
+		*s = "DW_AT_upper_bound"; break;
+	case DW_AT_use_location:
+		*s = "DW_AT_use_location"; break;
+	case DW_AT_use_UTF8:
+		*s = "DW_AT_use_UTF8"; break;
+	case DW_AT_variable_parameter:
+		*s = "DW_AT_variable_parameter"; break;
+	case DW_AT_virtuality:
+		*s = "DW_AT_virtuality"; break;
+	case DW_AT_visibility:
+		*s = "DW_AT_visibility"; break;
+	case DW_AT_vtable_elem_location:
+		*s = "DW_AT_vtable_elem_location"; break;
+	case DW_AT_sf_names:
+		*s = "DW_AT_sf_names"; break;
+	case DW_AT_src_info:
+		*s = "DW_AT_src_info"; break;
+	case DW_AT_mac_info:
+		*s = "DW_AT_mac_info"; break;
+	case DW_AT_src_coords:
+		*s = "DW_AT_src_coords"; break;
+	case DW_AT_body_begin:
+		*s = "DW_AT_body_begin"; break;
+	case DW_AT_body_end:
+		*s = "DW_AT_body_end"; break;
+	case DW_AT_MIPS_fde:
+		*s = "DW_AT_MIPS_fde"; break;
+	case DW_AT_MIPS_loop_begin:
+		*s = "DW_AT_MIPS_loop_begin"; break;
+	case DW_AT_MIPS_tail_loop_begin:
+		*s = "DW_AT_MIPS_tail_loop_begin"; break;
+	case DW_AT_MIPS_epilog_begin:
+		*s = "DW_AT_MIPS_epilog_begin"; break;
+	case DW_AT_MIPS_loop_unroll_factor:
+		*s = "DW_AT_MIPS_loop_unroll_factor"; break;
+	case DW_AT_MIPS_software_pipeline_depth:
+		*s = "DW_AT_MIPS_software_pipeline_depth"; break;
+	case DW_AT_MIPS_linkage_name:
+		*s = "DW_AT_MIPS_linkage_name"; break;
+	case DW_AT_MIPS_stride:
+		*s = "DW_AT_MIPS_stride"; break;
+	case DW_AT_MIPS_abstract_name:
+		*s = "DW_AT_MIPS_abstract_name"; break;
+	case DW_AT_MIPS_clone_origin:
+		*s = "DW_AT_MIPS_clone_origin"; break;
+	case DW_AT_MIPS_has_inlines:
+		*s = "DW_AT_MIPS_has_inlines"; break;
+	case DW_AT_MIPS_stride_byte:
+		*s = "DW_AT_MIPS_stride_byte"; break;
+	case DW_AT_MIPS_stride_elem:
+		*s = "DW_AT_MIPS_stride_elem"; break;
+	case DW_AT_MIPS_ptr_dopetype:
+		*s = "DW_AT_MIPS_ptr_dopetype"; break;
+	case DW_AT_MIPS_allocatable_dopetype:
+		*s = "DW_AT_MIPS_allocatable_dopetype"; break;
+	case DW_AT_MIPS_assumed_shape_dopetype:
+		*s = "DW_AT_MIPS_assumed_shape_dopetype"; break;
+	case DW_AT_MIPS_assumed_size:
+		*s = "DW_AT_MIPS_assumed_size"; break;
+	case DW_AT_GNU_vector:
+		*s = "DW_AT_GNU_vector"; break;
+	case DW_AT_GNU_guarded_by:
+		*s = "DW_AT_GNU_guarded_by"; break;
+	case DW_AT_GNU_pt_guarded_by:
+		*s = "DW_AT_GNU_pt_guarded_by"; break;
+	case DW_AT_GNU_guarded:
+		*s = "DW_AT_GNU_guarded"; break;
+	case DW_AT_GNU_pt_guarded:
+		*s = "DW_AT_GNU_pt_guarded"; break;
+	case DW_AT_GNU_locks_excluded:
+		*s = "DW_AT_GNU_locks_excluded"; break;
+	case DW_AT_GNU_exclusive_locks_required:
+		*s = "DW_AT_GNU_exclusive_locks_required"; break;
+	case DW_AT_GNU_shared_locks_required:
+		*s = "DW_AT_GNU_shared_locks_required"; break;
+	case DW_AT_GNU_odr_signature:
+		*s = "DW_AT_GNU_odr_signature"; break;
+	case DW_AT_GNU_template_name:
+		*s = "DW_AT_GNU_template_name"; break;
+	case DW_AT_GNU_call_site_value:
+		*s = "DW_AT_GNU_call_site_value"; break;
+	case DW_AT_GNU_call_site_data_value:
+		*s = "DW_AT_GNU_call_site_data_value"; break;
+	case DW_AT_GNU_call_site_target:
+		*s = "DW_AT_GNU_call_site_target"; break;
+	case DW_AT_GNU_call_site_target_clobbered:
+		*s = "DW_AT_GNU_call_site_target_clobbered"; break;
+	case DW_AT_GNU_tail_call:
+		*s = "DW_AT_GNU_tail_call"; break;
+	case DW_AT_GNU_all_tail_call_sites:
+		*s = "DW_AT_GNU_all_tail_call_sites"; break;
+	case DW_AT_GNU_all_call_sites:
+		*s = "DW_AT_GNU_all_call_sites"; break;
+	case DW_AT_GNU_all_source_call_sites:
+		*s = "DW_AT_GNU_all_source_call_sites"; break;
+	case DW_AT_APPLE_optimized:
+		*s = "DW_AT_APPLE_optimized"; break;
+	case DW_AT_APPLE_flags:
+		*s = "DW_AT_APPLE_flags"; break;
+	case DW_AT_APPLE_isa:
+		*s = "DW_AT_APPLE_isa"; break;
+	case DW_AT_APPLE_block:
+		*s = "DW_AT_APPLE_block"; break;
+	case DW_AT_APPLE_major_runtime_vers:
+		*s = "DW_AT_APPLE_major_runtime_vers"; break;
+	case DW_AT_APPLE_runtime_class:
+		*s = "DW_AT_APPLE_runtime_class"; break;
+	case DW_AT_APPLE_omit_frame_ptr:
+		*s = "DW_AT_APPLE_omit_frame_ptr"; break;
+	case DW_AT_APPLE_property_name:
+		*s = "DW_AT_APPLE_property_name"; break;
+	case DW_AT_APPLE_property_getter:
+		*s = "DW_AT_APPLE_property_getter"; break;
+	case DW_AT_APPLE_property_setter:
+		*s = "DW_AT_APPLE_property_setter"; break;
+	case DW_AT_APPLE_property_attribute:
+		*s = "DW_AT_APPLE_property_attribute"; break;
+	case DW_AT_APPLE_objc_complete_type:
+		*s = "DW_AT_APPLE_objc_complete_type"; break;
+	case DW_AT_APPLE_property:
+		*s = "DW_AT_APPLE_property"; break;
+	default:
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_ATE_name(unsigned ate, const char **s)
+{
+
+	assert(s != NULL);
+
+	switch(ate) {
+	case DW_ATE_address:
+		*s = "DW_ATE_address"; break;
+	case DW_ATE_boolean:
+		*s = "DW_ATE_boolean"; break;
+	case DW_ATE_complex_float:
+		*s = "DW_ATE_complex_float"; break;
+	case DW_ATE_float:
+		*s = "DW_ATE_float"; break;
+	case DW_ATE_signed:
+		*s = "DW_ATE_signed"; break;
+	case DW_ATE_signed_char:
+		*s = "DW_ATE_signed_char"; break;
+	case DW_ATE_unsigned:
+		*s = "DW_ATE_unsigned"; break;
+	case DW_ATE_unsigned_char:
+		*s = "DW_ATE_unsigned_char"; break;
+	case DW_ATE_imaginary_float:
+		*s = "DW_ATE_imaginary_float"; break;
+	case DW_ATE_packed_decimal:
+		*s = "DW_ATE_packed_decimal"; break;
+	case DW_ATE_numeric_string:
+		*s = "DW_ATE_numeric_string"; break;
+	case DW_ATE_edited:
+		*s = "DW_ATE_edited"; break;
+	case DW_ATE_signed_fixed:
+		*s = "DW_ATE_signed_fixed"; break;
+	case DW_ATE_unsigned_fixed:
+		*s = "DW_ATE_unsigned_fixed"; break;
+	case DW_ATE_decimal_float:
+		*s = "DW_ATE_decimal_float"; break;
+	case DW_ATE_lo_user:
+		*s = "DW_ATE_lo_user"; break;
+	case DW_ATE_hi_user:
+		*s = "DW_ATE_hi_user"; break;
+	default:
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_CC_name(unsigned cc, const char **s)
+{
+
+	assert(s != NULL);
+
+	switch (cc) {
+	case DW_CC_normal:
+		*s = "DW_CC_normal"; break;
+	case DW_CC_program:
+		*s = "DW_CC_program"; break;
+	case DW_CC_nocall:
+		*s = "DW_CC_nocall"; break;
+	case DW_CC_lo_user:
+		*s = "DW_CC_lo_user"; break;
+	case DW_CC_hi_user:
+		*s = "DW_CC_hi_user"; break;
+	default:
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_CFA_name(unsigned cfa, const char **s)
+{
+
+	assert(s != NULL);
+
+	switch (cfa) {
+	case DW_CFA_advance_loc:
+		*s = "DW_CFA_advance_loc"; break;
+	case DW_CFA_offset:
+		*s = "DW_CFA_offset"; break;
+	case DW_CFA_restore:
+		*s = "DW_CFA_restore"; break;
+	case DW_CFA_nop:
+		*s = "DW_CFA_nop"; break;
+	case DW_CFA_set_loc:
+		*s = "DW_CFA_set_loc"; break;
+	case DW_CFA_advance_loc1:
+		*s = "DW_CFA_advance_loc1"; break;
+	case DW_CFA_advance_loc2:
+		*s = "DW_CFA_advance_loc2"; break;
+	case DW_CFA_advance_loc4:
+		*s = "DW_CFA_advance_loc4"; break;
+	case DW_CFA_offset_extended:
+		*s = "DW_CFA_offset_extended"; break;
+	case DW_CFA_restore_extended:
+		*s = "DW_CFA_restore_extended"; break;
+	case DW_CFA_undefined:
+		*s = "DW_CFA_undefined"; break;
+	case DW_CFA_same_value:
+		*s = "DW_CFA_same_value"; break;
+	case DW_CFA_register:
+		*s = "DW_CFA_register"; break;
+	case DW_CFA_remember_state:
+		*s = "DW_CFA_remember_state"; break;
+	case DW_CFA_restore_state:
+		*s = "DW_CFA_restore_state"; break;
+	case DW_CFA_def_cfa:
+		*s = "DW_CFA_def_cfa"; break;
+	case DW_CFA_def_cfa_register:
+		*s = "DW_CFA_def_cfa_register"; break;
+	case DW_CFA_def_cfa_offset:
+		*s = "DW_CFA_def_cfa_offset"; break;
+	case DW_CFA_def_cfa_expression:
+		*s = "DW_CFA_def_cfa_expression"; break;
+	case DW_CFA_expression:
+		*s = "DW_CFA_expression"; break;
+	case DW_CFA_offset_extended_sf:
+		*s = "DW_CFA_offset_extended_sf"; break;
+	case DW_CFA_def_cfa_sf:
+		*s = "DW_CFA_def_cfa_sf"; break;
+	case DW_CFA_def_cfa_offset_sf:
+		*s = "DW_CFA_def_cfa_offset_sf"; break;
+	case DW_CFA_val_offset:
+		*s = "DW_CFA_val_offset"; break;
+	case DW_CFA_val_offset_sf:
+		*s = "DW_CFA_val_offset_sf"; break;
+	case DW_CFA_val_expression:
+		*s = "DW_CFA_val_expression"; break;
+	case DW_CFA_lo_user:
+		*s = "DW_CFA_lo_user"; break;
+	case DW_CFA_high_user:
+		*s = "DW_CFA_high_user"; break;
+	default:
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_CHILDREN_name(unsigned children, const char **s)
+{
+
+	assert(s != NULL);
+
+	switch (children) {
+	case DW_CHILDREN_no:
+		*s = "DW_CHILDREN_no"; break;
+	case DW_CHILDREN_yes:
+		*s = "DW_CHILDREN_yes"; break;
+	default:
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_FORM_name(unsigned form, const char **s)
+{
+
+	assert(s != NULL);
+
+	switch (form) {
+	case DW_FORM_addr:
+		*s = "DW_FORM_addr"; break;
+	case DW_FORM_block:
+		*s = "DW_FORM_block"; break;
+	case DW_FORM_block1:
+		*s = "DW_FORM_block1"; break;
+	case DW_FORM_block2:
+		*s = "DW_FORM_block2"; break;
+	case DW_FORM_block4:
+		*s = "DW_FORM_block4"; break;
+	case DW_FORM_data1:
+		*s = "DW_FORM_data1"; break;
+	case DW_FORM_data2:
+		*s = "DW_FORM_data2"; break;
+	case DW_FORM_data4:
+		*s = "DW_FORM_data4"; break;
+	case DW_FORM_data8:
+		*s = "DW_FORM_data8"; break;
+	case DW_FORM_exprloc:
+		*s = "DW_FORM_exprloc"; break;
+	case DW_FORM_flag:
+		*s = "DW_FORM_flag"; break;
+	case DW_FORM_flag_present:
+		*s = "DW_FORM_flag_present"; break;
+	case DW_FORM_indirect:
+		*s = "DW_FORM_indirect"; break;
+	case DW_FORM_ref1:
+		*s = "DW_FORM_ref1"; break;
+	case DW_FORM_ref2:
+		*s = "DW_FORM_ref2"; break;
+	case DW_FORM_ref4:
+		*s = "DW_FORM_ref4"; break;
+	case DW_FORM_ref8:
+		*s = "DW_FORM_ref8"; break;
+	case DW_FORM_ref_addr:
+		*s = "DW_FORM_ref_addr"; break;
+	case DW_FORM_ref_sig8:
+		*s = "DW_FORM_ref_sig8"; break;
+	case DW_FORM_ref_udata:
+		*s = "DW_FORM_ref_udata"; break;
+	case DW_FORM_sdata:
+		*s = "DW_FORM_sdata"; break;
+	case DW_FORM_sec_offset:
+		*s = "DW_FORM_sec_offset"; break;
+	case DW_FORM_string:
+		*s = "DW_FORM_string"; break;
+	case DW_FORM_strp:
+		*s = "DW_FORM_strp"; break;
+	case DW_FORM_udata:
+		*s = "DW_FORM_udata"; break;
+	default:
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_DS_name(unsigned ds, const char **s)
+{
+
+	assert(s != NULL);
+
+	switch (ds) {
+	case DW_DS_unsigned:
+		*s = "DW_DS_unsigned"; break;
+	case DW_DS_leading_overpunch:
+		*s = "DW_DS_leading_overpunch"; break;
+	case DW_DS_trailing_overpunch:
+		*s = "DW_DS_trailing_overpunch"; break;
+	case DW_DS_leading_separate:
+		*s = "DW_DS_leading_separate"; break;
+	case DW_DS_trailing_separate:
+		*s = "DW_DS_trailing_separate";
+	default:
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_DSC_name(unsigned dsc, const char **s)
+{
+
+	assert(s != NULL);
+
+	switch (dsc) {
+	case DW_DSC_label:
+		*s = "DW_DSC_label"; break;
+	case DW_DSC_range:
+		*s = "DW_DSC_range"; break;
+	default:
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_EH_name(unsigned eh, const char **s)
+{
+
+	assert(s != NULL);
+
+	switch (eh) {
+	case DW_EH_PE_absptr:
+		*s = "DW_EH_PE_absptr"; break;
+	case DW_EH_PE_uleb128:
+		*s = "DW_EH_PE_uleb128"; break;
+	case DW_EH_PE_udata2:
+		*s = "DW_EH_PE_udata2"; break;
+	case DW_EH_PE_udata4:
+		*s = "DW_EH_PE_udata4"; break;
+	case DW_EH_PE_udata8:
+		*s = "DW_EH_PE_udata8"; break;
+	case DW_EH_PE_sleb128:
+		*s = "DW_EH_PE_sleb128"; break;
+	case DW_EH_PE_sdata2:
+		*s = "DW_EH_PE_sdata2"; break;
+	case DW_EH_PE_sdata4:
+		*s = "DW_EH_PE_sdata4"; break;
+	case DW_EH_PE_sdata8:
+		*s = "DW_EH_PE_sdata8"; break;
+	case DW_EH_PE_pcrel:
+		*s = "DW_EH_PE_pcrel"; break;
+	case DW_EH_PE_textrel:
+		*s = "DW_EH_PE_textrel"; break;
+	case DW_EH_PE_datarel:
+		*s = "DW_EH_PE_datarel"; break;
+	case DW_EH_PE_funcrel:
+		*s = "DW_EH_PE_funcrel"; break;
+	case DW_EH_PE_aligned:
+		*s = "DW_EH_PE_aligned"; break;
+	case DW_EH_PE_omit:
+		*s = "DW_EH_PE_omit"; break;
+	default:
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_END_name(unsigned end, const char **s)
+{
+
+	assert(s != NULL);
+
+	switch (end) {
+	case DW_END_default:
+		*s = "DW_END_default"; break;
+	case DW_END_big:
+		*s = "DW_END_big"; break;
+	case DW_END_little:
+		*s = "DW_END_little"; break;
+	case DW_END_lo_user:
+		*s = "DW_END_lo_user"; break;
+	case DW_END_high_user:
+		*s = "DW_END_high_user"; break;
+	default:
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_ID_name(unsigned id, const char **s)
+{
+
+	assert(s != NULL);
+
+	switch (id) {
+	case DW_ID_case_sensitive:
+		*s = "DW_ID_case_sensitive"; break;
+	case DW_ID_up_case:
+		*s = "DW_ID_up_case"; break;
+	case DW_ID_down_case:
+		*s = "DW_ID_down_case"; break;
+	case DW_ID_case_insensitive:
+		*s = "DW_ID_case_insensitive"; break;
+	default:
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_INL_name(unsigned inl, const char **s)
+{
+
+	assert(s != NULL);
+
+	switch (inl) {
+	case DW_INL_not_inlined:
+		*s = "DW_INL_not_inlined"; break;
+	case DW_INL_inlined:
+		*s = "DW_INL_inlined"; break;
+	case DW_INL_declared_not_inlined:
+		*s = "DW_INL_declared_not_inlined"; break;
+	case DW_INL_declared_inlined:
+		*s = "DW_INL_declared_inlined"; break;
+	default:
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_LANG_name(unsigned lang, const char **s)
+{
+
+	assert(s != NULL);
+
+	switch (lang) {
+	case DW_LANG_C89:
+		*s = "DW_LANG_C89"; break;
+	case DW_LANG_C:
+		*s = "DW_LANG_C"; break;
+	case DW_LANG_Ada83:
+		*s = "DW_LANG_Ada83"; break;
+	case DW_LANG_C_plus_plus:
+		*s = "DW_LANG_C_plus_plus"; break;
+	case DW_LANG_Cobol74:
+		*s = "DW_LANG_Cobol74"; break;
+	case DW_LANG_Cobol85:
+		*s = "DW_LANG_Cobol85"; break;
+	case DW_LANG_Fortran77:
+		*s = "DW_LANG_Fortran77"; break;
+	case DW_LANG_Fortran90:
+		*s = "DW_LANG_Fortran90"; break;
+	case DW_LANG_Pascal83:
+		*s = "DW_LANG_Pascal83"; break;
+	case DW_LANG_Modula2:
+		*s = "DW_LANG_Modula2"; break;
+	case DW_LANG_Java:
+		*s = "DW_LANG_Java"; break;
+	case DW_LANG_C99:
+		*s = "DW_LANG_C99"; break;
+	case DW_LANG_Ada95:
+		*s = "DW_LANG_Ada95"; break;
+	case DW_LANG_Fortran95:
+		*s = "DW_LANG_Fortran95"; break;
+	case DW_LANG_PLI:
+		*s = "DW_LANG_PLI"; break;
+	case DW_LANG_ObjC:
+		*s = "DW_LANG_ObjC"; break;
+	case DW_LANG_ObjC_plus_plus:
+		*s = "DW_LANG_ObjC_plus_plus"; break;
+	case DW_LANG_UPC:
+		*s = "DW_LANG_UPC"; break;
+	case DW_LANG_D:
+		*s = "DW_LANG_D"; break;
+	case DW_LANG_Python:
+		*s = "DW_LANG_Python"; break;
+	case DW_LANG_OpenCL:
+		*s = "DW_LANG_OpenCL"; break;
+	case DW_LANG_Go:
+		*s = "DW_LANG_Go"; break;
+	case DW_LANG_Modula3:
+		*s = "DW_LANG_Modula3"; break;
+	case DW_LANG_Haskell:
+		*s = "DW_LANG_Haskell"; break;
+	case DW_LANG_C_plus_plus_03:
+		*s = "DW_LANG_C_plus_plus_03"; break;
+	case DW_LANG_C_plus_plus_11:
+		*s = "DW_LANG_C_plus_plus_11"; break;
+	case DW_LANG_OCaml:
+		*s = "DW_LANG_OCaml"; break;
+	case DW_LANG_Rust:
+		*s = "DW_LANG_Rust"; break;
+	case DW_LANG_C11:
+		*s = "DW_LANG_C11"; break;
+	case DW_LANG_Swift:
+		*s = "DW_LANG_Swift"; break;
+	case DW_LANG_Julia:
+		*s = "DW_LANG_Julia"; break;
+	case DW_LANG_Dylan:
+		*s = "DW_LANG_Dylan"; break;
+	case DW_LANG_C_plus_plus_14:
+		*s = "DW_LANG_C_plus_plus_14"; break;
+	case DW_LANG_Fortran03:
+		*s = "DW_LANG_Fortran03"; break;
+	case DW_LANG_Fortran08:
+		*s = "DW_LANG_Fortran08"; break;
+	case DW_LANG_RenderScript:
+		*s = "DW_LANG_RenderScript"; break;
+	case DW_LANG_BLISS:
+		*s = "DW_LANG_BLISS"; break;
+	case DW_LANG_lo_user:
+		*s = "DW_LANG_lo_user"; break;
+	case DW_LANG_Mips_Assembler:
+		*s = "DW_LANG_Mips_Assembler"; break;
+	case DW_LANG_hi_user:
+		*s = "DW_LANG_hi_user"; break;
+	default:
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_LNE_name(unsigned lne, const char **s)
+{
+
+	assert(s != NULL);
+
+	switch (lne) {
+	case DW_LNE_end_sequence:
+		*s = "DW_LNE_end_sequence"; break;
+	case DW_LNE_set_address:
+		*s = "DW_LNE_set_address"; break;
+	case DW_LNE_define_file:
+		*s = "DW_LNE_define_file"; break;
+	case DW_LNE_lo_user:
+		*s = "DW_LNE_lo_user"; break;
+	case DW_LNE_hi_user:
+		*s = "DW_LNE_hi_user"; break;
+	default:
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_LNS_name(unsigned lns, const char **s)
+{
+
+	assert(s != NULL);
+
+	switch (lns) {
+	case DW_LNS_copy:
+		*s = "DW_LNS_copy"; break;
+	case DW_LNS_advance_pc:
+		*s = "DW_LNS_advance_pc"; break;
+	case DW_LNS_advance_line:
+		*s = "DW_LNS_advance_line"; break;
+	case DW_LNS_set_file:
+		*s = "DW_LNS_set_file"; break;
+	case DW_LNS_set_column:
+		*s = "DW_LNS_set_column"; break;
+	case DW_LNS_negate_stmt:
+		*s = "DW_LNS_negate_stmt"; break;
+	case DW_LNS_set_basic_block:
+		*s = "DW_LNS_set_basic_block"; break;
+	case DW_LNS_const_add_pc:
+		*s = "DW_LNS_const_add_pc"; break;
+	case DW_LNS_fixed_advance_pc:
+		*s = "DW_LNS_fixed_advance_pc"; break;
+	case DW_LNS_set_prologue_end:
+		*s = "DW_LNS_set_prologue_end"; break;
+	case DW_LNS_set_epilogue_begin:
+		*s = "DW_LNS_set_epilogue_begin"; break;
+	case DW_LNS_set_isa:
+		*s = "DW_LNS_set_isa"; break;
+	default:
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_MACINFO_name(unsigned mi, const char **s)
+{
+
+	assert(s != NULL);
+
+	switch (mi) {
+	case DW_MACINFO_define:
+		*s = "DW_MACINFO_define"; break;
+	case DW_MACINFO_undef:
+		*s = "DW_MACINFO_undef"; break;
+	case DW_MACINFO_start_file:
+		*s = "DW_MACINFO_start_file"; break;
+	case DW_MACINFO_end_file:
+		*s = "DW_MACINFO_end_file"; break;
+	case DW_MACINFO_vendor_ext:
+		*s = "DW_MACINFO_vendor_ext"; break;
+	default:
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_OP_name(unsigned op, const char **s)
+{
+
+	assert(s != NULL);
+
+	switch (op) {
+	case DW_OP_deref:
+		*s = "DW_OP_deref"; break;
+	case DW_OP_reg0:
+		*s = "DW_OP_reg0"; break;
+	case DW_OP_reg1:
+		*s = "DW_OP_reg1"; break;
+	case DW_OP_reg2:
+		*s = "DW_OP_reg2"; break;
+	case DW_OP_reg3:
+		*s = "DW_OP_reg3"; break;
+	case DW_OP_reg4:
+		*s = "DW_OP_reg4"; break;
+	case DW_OP_reg5:
+		*s = "DW_OP_reg5"; break;
+	case DW_OP_reg6:
+		*s = "DW_OP_reg6"; break;
+	case DW_OP_reg7:
+		*s = "DW_OP_reg7"; break;
+	case DW_OP_reg8:
+		*s = "DW_OP_reg8"; break;
+	case DW_OP_reg9:
+		*s = "DW_OP_reg9"; break;
+	case DW_OP_reg10:
+		*s = "DW_OP_reg10"; break;
+	case DW_OP_reg11:
+		*s = "DW_OP_reg11"; break;
+	case DW_OP_reg12:
+		*s = "DW_OP_reg12"; break;
+	case DW_OP_reg13:
+		*s = "DW_OP_reg13"; break;
+	case DW_OP_reg14:
+		*s = "DW_OP_reg14"; break;
+	case DW_OP_reg15:
+		*s = "DW_OP_reg15"; break;
+	case DW_OP_reg16:
+		*s = "DW_OP_reg16"; break;
+	case DW_OP_reg17:
+		*s = "DW_OP_reg17"; break;
+	case DW_OP_reg18:
+		*s = "DW_OP_reg18"; break;
+	case DW_OP_reg19:
+		*s = "DW_OP_reg19"; break;
+	case DW_OP_reg20:
+		*s = "DW_OP_reg20"; break;
+	case DW_OP_reg21:
+		*s = "DW_OP_reg21"; break;
+	case DW_OP_reg22:
+		*s = "DW_OP_reg22"; break;
+	case DW_OP_reg23:
+		*s = "DW_OP_reg23"; break;
+	case DW_OP_reg24:
+		*s = "DW_OP_reg24"; break;
+	case DW_OP_reg25:
+		*s = "DW_OP_reg25"; break;
+	case DW_OP_reg26:
+		*s = "DW_OP_reg26"; break;
+	case DW_OP_reg27:
+		*s = "DW_OP_reg27"; break;
+	case DW_OP_reg28:
+		*s = "DW_OP_reg28"; break;
+	case DW_OP_reg29:
+		*s = "DW_OP_reg29"; break;
+	case DW_OP_reg30:
+		*s = "DW_OP_reg30"; break;
+	case DW_OP_reg31:
+		*s = "DW_OP_reg31"; break;
+	case DW_OP_lit0:
+		*s = "DW_OP_lit0"; break;
+	case DW_OP_lit1:
+		*s = "DW_OP_lit1"; break;
+	case DW_OP_lit2:
+		*s = "DW_OP_lit2"; break;
+	case DW_OP_lit3:
+		*s = "DW_OP_lit3"; break;
+	case DW_OP_lit4:
+		*s = "DW_OP_lit4"; break;
+	case DW_OP_lit5:
+		*s = "DW_OP_lit5"; break;
+	case DW_OP_lit6:
+		*s = "DW_OP_lit6"; break;
+	case DW_OP_lit7:
+		*s = "DW_OP_lit7"; break;
+	case DW_OP_lit8:
+		*s = "DW_OP_lit8"; break;
+	case DW_OP_lit9:
+		*s = "DW_OP_lit9"; break;
+	case DW_OP_lit10:
+		*s = "DW_OP_lit10"; break;
+	case DW_OP_lit11:
+		*s = "DW_OP_lit11"; break;
+	case DW_OP_lit12:
+		*s = "DW_OP_lit12"; break;
+	case DW_OP_lit13:
+		*s = "DW_OP_lit13"; break;
+	case DW_OP_lit14:
+		*s = "DW_OP_lit14"; break;
+	case DW_OP_lit15:
+		*s = "DW_OP_lit15"; break;
+	case DW_OP_lit16:
+		*s = "DW_OP_lit16"; break;
+	case DW_OP_lit17:
+		*s = "DW_OP_lit17"; break;
+	case DW_OP_lit18:
+		*s = "DW_OP_lit18"; break;
+	case DW_OP_lit19:
+		*s = "DW_OP_lit19"; break;
+	case DW_OP_lit20:
+		*s = "DW_OP_lit20"; break;
+	case DW_OP_lit21:
+		*s = "DW_OP_lit21"; break;
+	case DW_OP_lit22:
+		*s = "DW_OP_lit22"; break;
+	case DW_OP_lit23:
+		*s = "DW_OP_lit23"; break;
+	case DW_OP_lit24:
+		*s = "DW_OP_lit24"; break;
+	case DW_OP_lit25:
+		*s = "DW_OP_lit25"; break;
+	case DW_OP_lit26:
+		*s = "DW_OP_lit26"; break;
+	case DW_OP_lit27:
+		*s = "DW_OP_lit27"; break;
+	case DW_OP_lit28:
+		*s = "DW_OP_lit28"; break;
+	case DW_OP_lit29:
+		*s = "DW_OP_lit29"; break;
+	case DW_OP_lit30:
+		*s = "DW_OP_lit30"; break;
+	case DW_OP_lit31:
+		*s = "DW_OP_lit31"; break;
+	case DW_OP_dup:
+		*s = "DW_OP_dup"; break;
+	case DW_OP_drop:
+		*s = "DW_OP_drop"; break;
+	case DW_OP_over:
+		*s = "DW_OP_over"; break;
+	case DW_OP_swap:
+		*s = "DW_OP_swap"; break;
+	case DW_OP_rot:
+		*s = "DW_OP_rot"; break;
+	case DW_OP_xderef:
+		*s = "DW_OP_xderef"; break;
+	case DW_OP_abs:
+		*s = "DW_OP_abs"; break;
+	case DW_OP_and:
+		*s = "DW_OP_and"; break;
+	case DW_OP_div:
+		*s = "DW_OP_div"; break;
+	case DW_OP_minus:
+		*s = "DW_OP_minus"; break;
+	case DW_OP_mod:
+		*s = "DW_OP_mod"; break;
+	case DW_OP_mul:
+		*s = "DW_OP_mul"; break;
+	case DW_OP_neg:
+		*s = "DW_OP_neg"; break;
+	case DW_OP_not:
+		*s = "DW_OP_not"; break;
+	case DW_OP_or:
+		*s = "DW_OP_or"; break;
+	case DW_OP_plus:
+		*s = "DW_OP_plus"; break;
+	case DW_OP_shl:
+		*s = "DW_OP_shl"; break;
+	case DW_OP_shr:
+		*s = "DW_OP_shr"; break;
+	case DW_OP_shra:
+		*s = "DW_OP_shra"; break;
+	case DW_OP_xor:
+		*s = "DW_OP_xor"; break;
+	case DW_OP_eq:
+		*s = "DW_OP_eq"; break;
+	case DW_OP_ge:
+		*s = "DW_OP_ge"; break;
+	case DW_OP_gt:
+		*s = "DW_OP_gt"; break;
+	case DW_OP_le:
+		*s = "DW_OP_le"; break;
+	case DW_OP_lt:
+		*s = "DW_OP_lt"; break;
+	case DW_OP_ne:
+		*s = "DW_OP_ne"; break;
+	case DW_OP_nop:
+		*s = "DW_OP_nop"; break;
+	case DW_OP_const1u:
+		*s = "DW_OP_const1u"; break;
+	case DW_OP_const1s:
+		*s = "DW_OP_const1s"; break;
+	case DW_OP_pick:
+		*s = "DW_OP_pick"; break;
+	case DW_OP_deref_size:
+		*s = "DW_OP_deref_size"; break;
+	case DW_OP_xderef_size:
+		*s = "DW_OP_xderef_size"; break;
+	case DW_OP_const2u:
+		*s = "DW_OP_const2u"; break;
+	case DW_OP_const2s:
+		*s = "DW_OP_const2s"; break;
+	case DW_OP_bra:
+		*s = "DW_OP_bra"; break;
+	case DW_OP_skip:
+		*s = "DW_OP_skip"; break;
+	case DW_OP_const4u:
+		*s = "DW_OP_const4u"; break;
+	case DW_OP_const4s:
+		*s = "DW_OP_const4s"; break;
+	case DW_OP_const8u:
+		*s = "DW_OP_const8u"; break;
+	case DW_OP_const8s:
+		*s = "DW_OP_const8s"; break;
+	case DW_OP_constu:
+		*s = "DW_OP_constu"; break;
+	case DW_OP_plus_uconst:
+		*s = "DW_OP_plus_uconst"; break;
+	case DW_OP_regx:
+		*s = "DW_OP_regx"; break;
+	case DW_OP_piece:
+		*s = "DW_OP_piece"; break;
+	case DW_OP_consts:
+		*s = "DW_OP_consts"; break;
+	case DW_OP_breg0:
+		*s = "DW_OP_breg0"; break;
+	case DW_OP_breg1:
+		*s = "DW_OP_breg1"; break;
+	case DW_OP_breg2:
+		*s = "DW_OP_breg2"; break;
+	case DW_OP_breg3:
+		*s = "DW_OP_breg3"; break;
+	case DW_OP_breg4:
+		*s = "DW_OP_breg4"; break;
+	case DW_OP_breg5:
+		*s = "DW_OP_breg5"; break;
+	case DW_OP_breg6:
+		*s = "DW_OP_breg6"; break;
+	case DW_OP_breg7:
+		*s = "DW_OP_breg7"; break;
+	case DW_OP_breg8:
+		*s = "DW_OP_breg8"; break;
+	case DW_OP_breg9:
+		*s = "DW_OP_breg9"; break;
+	case DW_OP_breg10:
+		*s = "DW_OP_breg10"; break;
+	case DW_OP_breg11:
+		*s = "DW_OP_breg11"; break;
+	case DW_OP_breg12:
+		*s = "DW_OP_breg12"; break;
+	case DW_OP_breg13:
+		*s = "DW_OP_breg13"; break;
+	case DW_OP_breg14:
+		*s = "DW_OP_breg14"; break;
+	case DW_OP_breg15:
+		*s = "DW_OP_breg15"; break;
+	case DW_OP_breg16:
+		*s = "DW_OP_breg16"; break;
+	case DW_OP_breg17:
+		*s = "DW_OP_breg17"; break;
+	case DW_OP_breg18:
+		*s = "DW_OP_breg18"; break;
+	case DW_OP_breg19:
+		*s = "DW_OP_breg19"; break;
+	case DW_OP_breg20:
+		*s = "DW_OP_breg20"; break;
+	case DW_OP_breg21:
+		*s = "DW_OP_breg21"; break;
+	case DW_OP_breg22:
+		*s = "DW_OP_breg22"; break;
+	case DW_OP_breg23:
+		*s = "DW_OP_breg23"; break;
+	case DW_OP_breg24:
+		*s = "DW_OP_breg24"; break;
+	case DW_OP_breg25:
+		*s = "DW_OP_breg25"; break;
+	case DW_OP_breg26:
+		*s = "DW_OP_breg26"; break;
+	case DW_OP_breg27:
+		*s = "DW_OP_breg27"; break;
+	case DW_OP_breg28:
+		*s = "DW_OP_breg28"; break;
+	case DW_OP_breg29:
+		*s = "DW_OP_breg29"; break;
+	case DW_OP_breg30:
+		*s = "DW_OP_breg30"; break;
+	case DW_OP_breg31:
+		*s = "DW_OP_breg31"; break;
+	case DW_OP_fbreg:
+		*s = "DW_OP_fbreg"; break;
+	case DW_OP_bregx:
+		*s = "DW_OP_bregx"; break;
+	case DW_OP_addr:
+		*s = "DW_OP_addr"; break;
+	case DW_OP_push_object_address:
+		*s = "DW_OP_push_object_address"; break;
+	case DW_OP_call2:
+		*s = "DW_OP_call2"; break;
+	case DW_OP_call4:
+		*s = "DW_OP_call4"; break;
+	case DW_OP_call_ref:
+		*s = "DW_OP_call_ref"; break;
+	case DW_OP_form_tls_address:
+		*s = "DW_OP_form_tls_address"; break;
+	case DW_OP_call_frame_cfa:
+		*s = "DW_OP_call_frame_cfa"; break;
+	case DW_OP_bit_piece:
+		*s = "DW_OP_bit_piece"; break;
+	case DW_OP_implicit_value:
+		*s = "DW_OP_implicit_value"; break;
+	case DW_OP_stack_value:
+		*s = "DW_OP_stack_value"; break;
+	case DW_OP_GNU_push_tls_address:
+		*s = "DW_OP_GNU_push_tls_address"; break;
+	case DW_OP_GNU_uninit:
+		*s = "DW_OP_GNU_uninit"; break;
+	case DW_OP_GNU_encoded_addr:
+		*s = "DW_OP_GNU_encoded_addr"; break;
+	case DW_OP_GNU_implicit_pointer:
+		*s = "DW_OP_GNU_implicit_pointer"; break;
+	case DW_OP_GNU_entry_value:
+		*s = "DW_OP_GNU_entry_value"; break;
+	case DW_OP_GNU_const_type:
+		*s = "DW_OP_GNU_const_type"; break;
+	case DW_OP_GNU_regval_type:
+		*s = "DW_OP_GNU_regval_type"; break;
+	case DW_OP_GNU_deref_type:
+		*s = "DW_OP_GNU_deref_type"; break;
+	case DW_OP_GNU_convert:
+		*s = "DW_OP_GNU_convert"; break;
+	case DW_OP_GNU_reinterpret:
+		*s = "DW_OP_GNU_reinterpret"; break;
+	case DW_OP_GNU_parameter_ref:
+		*s = "DW_OP_GNU_parameter_ref"; break;
+	case DW_OP_GNU_addr_index:
+		*s = "DW_OP_GNU_addr_index"; break;
+	case DW_OP_GNU_const_index:
+		*s = "DW_OP_GNU_const_index"; break;
+	default:
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_ORD_name(unsigned ord, const char **s)
+{
+
+	assert(s != NULL);
+
+	switch (ord) {
+	case DW_ORD_row_major:
+		*s = "DW_ORD_row_major"; break;
+	case DW_ORD_col_major:
+		*s = "DW_ORD_col_major"; break;
+	default:
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_TAG_name(unsigned tag, const char **s)
+{
+
+	assert(s != NULL);
+
+	switch (tag) {
+	case DW_TAG_access_declaration:
+		*s = "DW_TAG_access_declaration"; break;
+	case DW_TAG_array_type:
+		*s = "DW_TAG_array_type"; break;
+	case DW_TAG_base_type:
+		*s = "DW_TAG_base_type"; break;
+	case DW_TAG_catch_block:
+		*s = "DW_TAG_catch_block"; break;
+	case DW_TAG_class_type:
+		*s = "DW_TAG_class_type"; break;
+	case DW_TAG_common_block:
+		*s = "DW_TAG_common_block"; break;
+	case DW_TAG_common_inclusion:
+		*s = "DW_TAG_common_inclusion"; break;
+	case DW_TAG_compile_unit:
+		*s = "DW_TAG_compile_unit"; break;
+	case DW_TAG_condition:
+		*s = "DW_TAG_condition"; break;
+	case DW_TAG_const_type:
+		*s = "DW_TAG_const_type"; break;
+	case DW_TAG_constant:
+		*s = "DW_TAG_constant"; break;
+	case DW_TAG_dwarf_procedure:
+		*s = "DW_TAG_dwarf_procedure"; break;
+	case DW_TAG_entry_point:
+		*s = "DW_TAG_entry_point"; break;
+	case DW_TAG_enumeration_type:
+		*s = "DW_TAG_enumeration_type"; break;
+	case DW_TAG_enumerator:
+		*s = "DW_TAG_enumerator"; break;
+	case DW_TAG_formal_parameter:
+		*s = "DW_TAG_formal_parameter"; break;
+	case DW_TAG_friend:
+		*s = "DW_TAG_friend"; break;
+	case DW_TAG_imported_declaration:
+		*s = "DW_TAG_imported_declaration"; break;
+	case DW_TAG_imported_module:
+		*s = "DW_TAG_imported_module"; break;
+	case DW_TAG_imported_unit:
+		*s = "DW_TAG_imported_unit"; break;
+	case DW_TAG_inheritance:
+		*s = "DW_TAG_inheritance"; break;
+	case DW_TAG_inlined_subroutine:
+		*s = "DW_TAG_inlined_subroutine"; break;
+	case DW_TAG_interface_type:
+		*s = "DW_TAG_interface_type"; break;
+	case DW_TAG_label:
+		*s = "DW_TAG_label"; break;
+	case DW_TAG_lexical_block:
+		*s = "DW_TAG_lexical_block"; break;
+	case DW_TAG_member:
+		*s = "DW_TAG_member"; break;
+	case DW_TAG_module:
+		*s = "DW_TAG_module"; break;
+	case DW_TAG_namelist:
+		*s = "DW_TAG_namelist"; break;
+	case DW_TAG_namelist_item:
+		*s = "DW_TAG_namelist_item"; break;
+	case DW_TAG_namespace:
+		*s = "DW_TAG_namespace"; break;
+	case DW_TAG_packed_type:
+		*s = "DW_TAG_packed_type"; break;
+	case DW_TAG_partial_unit:
+		*s = "DW_TAG_partial_unit"; break;
+	case DW_TAG_pointer_type:
+		*s = "DW_TAG_pointer_type"; break;
+	case DW_TAG_ptr_to_member_type:
+		*s = "DW_TAG_ptr_to_member_type"; break;
+	case DW_TAG_reference_type:
+		*s = "DW_TAG_reference_type"; break;
+	case DW_TAG_restrict_type:
+		*s = "DW_TAG_restrict_type"; break;
+	case DW_TAG_rvalue_reference_type:
+		*s = "DW_TAG_rvalue_reference_type"; break;
+	case DW_TAG_set_type:
+		*s = "DW_TAG_set_type"; break;
+	case DW_TAG_shared_type:
+		*s = "DW_TAG_shared_type"; break;
+	case DW_TAG_string_type:
+		*s = "DW_TAG_string_type"; break;
+	case DW_TAG_structure_type:
+		*s = "DW_TAG_structure_type"; break;
+	case DW_TAG_subprogram:
+		*s = "DW_TAG_subprogram"; break;
+	case DW_TAG_subrange_type:
+		*s = "DW_TAG_subrange_type"; break;
+	case DW_TAG_subroutine_type:
+		*s = "DW_TAG_subroutine_type"; break;
+	case DW_TAG_template_alias:
+		*s = "DW_TAG_template_alias"; break;
+	case DW_TAG_template_type_parameter:
+		*s = "DW_TAG_template_type_parameter"; break;
+	case DW_TAG_template_value_parameter:
+		*s = "DW_TAG_template_value_parameter"; break;
+	case DW_TAG_thrown_type:
+		*s = "DW_TAG_thrown_type"; break;
+	case DW_TAG_try_block:
+		*s = "DW_TAG_try_block"; break;
+	case DW_TAG_type_unit:
+		*s = "DW_TAG_type_unit"; break;
+	case DW_TAG_typedef:
+		*s = "DW_TAG_typedef"; break;
+	case DW_TAG_union_type:
+		*s = "DW_TAG_union_type"; break;
+	case DW_TAG_unspecified_parameters:
+		*s = "DW_TAG_unspecified_parameters"; break;
+	case DW_TAG_unspecified_type:
+		*s = "DW_TAG_unspecified_type"; break;
+	case DW_TAG_variable:
+		*s = "DW_TAG_variable"; break;
+	case DW_TAG_variant:
+		*s = "DW_TAG_variant"; break;
+	case DW_TAG_variant_part:
+		*s = "DW_TAG_variant_part"; break;
+	case DW_TAG_volatile_type:
+		*s = "DW_TAG_volatile_type"; break;
+	case DW_TAG_with_stmt:
+		*s = "DW_TAG_with_stmt"; break;
+	case DW_TAG_format_label:
+		*s = "DW_TAG_format_label"; break;
+	case DW_TAG_function_template:
+		*s = "DW_TAG_function_template"; break;
+	case DW_TAG_class_template:
+		*s = "DW_TAG_class_template"; break;
+	case DW_TAG_GNU_BINCL:
+		*s = "DW_TAG_GNU_BINCL"; break;
+	case DW_TAG_GNU_EINCL:
+		*s = "DW_TAG_GNU_EINCL"; break;
+	case DW_TAG_GNU_template_template_param:
+		*s = "DW_TAG_GNU_template_template_param"; break;
+	case DW_TAG_GNU_template_parameter_pack:
+		*s = "DW_TAG_GNU_template_parameter_pack"; break;
+	case DW_TAG_GNU_formal_parameter_pack:
+		*s = "DW_TAG_GNU_formal_parameter_pack"; break;
+	case DW_TAG_GNU_call_site:
+		*s = "DW_TAG_GNU_call_site"; break;
+	case DW_TAG_GNU_call_site_parameter:
+		*s = "DW_TAG_GNU_call_site_parameter"; break;
+	default:
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_VIRTUALITY_name(unsigned vir, const char **s)
+{
+
+	assert(s != NULL);
+
+	switch (vir) {
+	case DW_VIRTUALITY_none:
+		*s = "DW_VIRTUALITY_none"; break;
+	case DW_VIRTUALITY_virtual:
+		*s = "DW_VIRTUALITY_virtual"; break;
+	case DW_VIRTUALITY_pure_virtual:
+		*s = "DW_VIRTUALITY_pure_virtual"; break;
+	default:
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_VIS_name(unsigned vis, const char **s)
+{
+
+	assert(s != NULL);
+
+	switch (vis) {
+	case DW_VIS_local:
+		*s = "DW_VIS_local"; break;
+	case DW_VIS_exported:
+		*s = "DW_VIS_exported"; break;
+	case DW_VIS_qualified:
+		*s = "DW_VIS_qualified"; break;
+	default:
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	return (DW_DLV_OK);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_end_macro_file.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,90 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_end_macro_file.3 2073 2011-10-27 03:30:47Z jkoshy $
+.\"
+.Dd September 25, 2011
+.Os
+.Dt DWARF_END_MACRO_FILE 3
+.Sh NAME
+.Nm dwarf_end_macro_file
+.Nd mark the end of the current source file inclusion
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "int"
+.Fo dwarf_end_macro_file
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_Error *err"
+.Fa
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_end_macro_file
+marks the end of the current source file inclusion.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_end_macro_file
+returns
+.Dv DW_DLV_OK .
+In case of an error, function
+.Fn dwarf_end_macro_file
+returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_end_macro_file
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Ar dbg
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_def_macro 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3 ,
+.Xr dwarf_start_macro_file 3 ,
+.Xr dwarf_undef_macro 3 ,
+.Xr dwarf_vendor_ext 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_errmsg.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,67 @@
+.\" Copyright (c) 2009 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: dwarf_errmsg.3 2073 2011-10-27 03:30:47Z jkoshy $
+.\"
+.Dd December 12, 2009
+.Os
+.Dt DWARF_ERRMSG 3
+.Sh NAME
+.Nm dwarf_errmsg
+.Nd retrieve a human-readable string corresponding to a
+.Vt Dwarf_Error
+instance
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "const char *"
+.Fn dwarf_errmsg "Dwarf_Error err"
+.Sh DESCRIPTION
+Function
+.Fn dwarf_errmsg
+returns a
+.Dv NUL Ns - Ns
+terminated string for the error denoted by
+argument
+.Ar err .
+.Pp
+Argument
+.Ar err
+should be a valid handle to a
+.Vt Dwarf_Error
+instance.
+.Sh Memory Management
+The returned pointer should not be freed using
+.Xr free 3
+or
+.Xr dwarf_dealloc 3 .
+.Sh RETURN VALUES
+Function
+.Fn dwarf_errmsg
+returns a pointer to a
+.Dv NUL Ns - Ns
+terminated string.
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_errno 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_errmsg.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,90 @@
+/*-
+ * Copyright (c) 2007 John Birrell (jb@freebsd.org)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_errmsg.c 2975 2014-01-21 20:08:04Z kaiwang27 $");
+
+static const char *_libdwarf_errors[] = {
+#define	DEFINE_ERROR(N,S)		[DW_DLE_##N] = S
+	DEFINE_ERROR(NONE, "No Error"),
+	DEFINE_ERROR(ERROR, "An error"),
+	DEFINE_ERROR(NO_ENTRY, "No entry found"),
+	DEFINE_ERROR(ARGUMENT, "Invalid argument"),
+	DEFINE_ERROR(DEBUG_INFO_NULL, "Debug info NULL"),
+	DEFINE_ERROR(MEMORY, "Insufficient memory"),
+	DEFINE_ERROR(ELF, "ELF error"),
+	DEFINE_ERROR(CU_LENGTH_ERROR, "Invalid compilation unit data"),
+	DEFINE_ERROR(VERSION_STAMP_ERROR, "Unsupported version"),
+	DEFINE_ERROR(DEBUG_ABBREV_NULL, "Abbrev not found"),
+	DEFINE_ERROR(DIE_NO_CU_CONTEXT,	"No current compilation unit"),
+	DEFINE_ERROR(LOC_EXPR_BAD, "Invalid location expression"),
+	DEFINE_ERROR(EXPR_LENGTH_BAD, "Invalid DWARF expression length"),
+	DEFINE_ERROR(DEBUG_LOC_SECTION_SHORT, "Loclist section too short"),
+	DEFINE_ERROR(ATTR_FORM_BAD, "Invalid attribute form"),
+	DEFINE_ERROR(DEBUG_LINE_LENGTH_BAD, "Line info section too short"),
+	DEFINE_ERROR(LINE_FILE_NUM_BAD, "Invalid file number."),
+	DEFINE_ERROR(DIR_INDEX_BAD, "Invalid dir index."),
+	DEFINE_ERROR(DEBUG_FRAME_LENGTH_BAD, "Frame section too short"),
+	DEFINE_ERROR(NO_CIE_FOR_FDE, "FDE without corresponding CIE"),
+	DEFINE_ERROR(FRAME_AUGMENTATION_UNKNOWN, "Unknown CIE augmentation"),
+	DEFINE_ERROR(FRAME_INSTR_EXEC_ERROR, "Frame instruction exec error"),
+	DEFINE_ERROR(FRAME_VERSION_BAD, "Unsupported frame section version"),
+	DEFINE_ERROR(FRAME_TABLE_COL_BAD, "Invalid table column value"),
+	DEFINE_ERROR(DF_REG_NUM_TOO_HIGH, "Register number too large"),
+	DEFINE_ERROR(PC_NOT_IN_FDE_RANGE, "PC requested not in the FDE range"),
+	DEFINE_ERROR(ARANGE_OFFSET_BAD, "Invalid address range offset"),
+	DEFINE_ERROR(DEBUG_MACRO_INCONSISTENT, "Invalid macinfo data"),
+	DEFINE_ERROR(ELF_SECT_ERR, "Application callback failed"),
+	DEFINE_ERROR(NUM, "Unknown DWARF error")
+#undef	DEFINE_ERROR
+};
+
+const char *
+dwarf_errmsg_(Dwarf_Error *error)
+{
+	const char *p;
+
+	if (error == NULL)
+		return NULL;
+
+	if (error->err_error < 0 || error->err_error >= DW_DLE_NUM)
+		return _libdwarf_errors[DW_DLE_NUM];
+	else if (error->err_error == DW_DLE_NONE)
+		return _libdwarf_errors[DW_DLE_NONE];
+	else
+		p = _libdwarf_errors[error->err_error];
+
+	if (error->err_error == DW_DLE_ELF)
+		snprintf(error->err_msg, sizeof(error->err_msg),
+		    "ELF error : %s [%s(%d)]", elf_errmsg(error->err_elferror),
+		    error->err_func, error->err_line);
+	else
+		snprintf(error->err_msg, sizeof(error->err_msg),
+		    "%s [%s(%d)]", p, error->err_func, error->err_line);
+
+	return (const char *) error->err_msg;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_errno.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,58 @@
+.\" Copyright (c) 2009,2010 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: dwarf_errno.3 2073 2011-10-27 03:30:47Z jkoshy $
+.\"
+.Dd March 25, 2010
+.Os
+.Dt DWARF_ERRNO 3
+.Sh NAME
+.Nm dwarf_errno
+.Nd retrieve the error number corresponding to a
+.Vt Dwarf_Error
+instance
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fn dwarf_errno "Dwarf_Error err"
+.Sh DESCRIPTION
+Function
+.Fn dwarf_errno
+returns the error number associated with a
+.Vt Dwarf_Error
+instance.
+.Pp
+Argument
+.Ar err
+should be a valid handle to a
+.Vt Dwarf_Error
+instance.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_errno
+returns an integral value.
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_errmsg 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_expand_frame_instructions.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,182 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_expand_frame_instructions.3 3181 2015-04-10 13:22:51Z emaste $
+.\"
+.Dd November 9, 2011
+.Os
+.Dt DWARF_EXPAND_FRAME_INSTRUCTIONS 3
+.Sh NAME
+.Nm dwarf_expand_frame_instructions
+.Nd expand frame instructions
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_expand_frame_instructions
+.Fa "Dwarf_Cie cie"
+.Fa "Dwarf_Ptr instructions"
+.Fa "Dwarf_Unsigned len"
+.Fa "Dwarf_Frame_Op **ret_ops"
+.Fa "Dwarf_Signed *ret_opcnt"
+.Fa "Dwarf_Error *error"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_expand_frame_instructions
+translates DWARF frame instruction bytes into an array of
+.Vt Dwarf_Frame_Op
+descriptors.
+.Pp
+Argument
+.Ar cie
+should reference the CIE descriptor associated with the instructions
+to be translated.
+.Pp
+Arugment
+.Ar instructions
+should point to an array of frame instruction bytes, as
+returned by the functions
+.Xr dwarf_get_cie_info 3
+or
+.Xr dwarf_get_fde_instr_bytes 3 .
+.Pp
+Argument
+.Ar len
+should specify the number of the frame instruction bytes to be
+translated.
+.Pp
+Argument
+.Ar ret_ops
+should point to a location that will be set to a pointer to
+an array of translated
+.Vt Dwarf_Frame_Op
+descriptors.
+.Pp
+Argument
+.Ar ret_opcnt
+should point to a location that will hold the total number of the
+returned descriptors.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Ss Memory Management
+The memory area used for the descriptor array returned in argument
+.Ar ret_ops
+is allocated by
+.Lb libdwarf .
+Application code should use function
+.Xr dwarf_dealloc 3
+with type
+.Dv DW_DLA_FRAME_BLOCK
+to free the memory area when the descriptor array is no longer needed.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_expand_frame_instructions
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_expand_frame_instructions
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar cie ,
+.Ar instructions ,
+.Ar ret_ops
+or
+.Ar ret_opcnt
+was NULL.
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Ar len
+was 0.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of
+this function.
+.It Bq Er DW_DLE_FRAME_INSTR_EXEC_ERROR
+An unknown instruction was found in the instruction bytes provided
+in argument
+.Ar instructions .
+.El
+.Sh EXAMPLE
+To retrieve and expand the frame instructions for a given FDE
+descriptor, use:
+.Bd -literal -offset indent
+Dwarf_Dbg dbg;
+Dwarf_Cie cie;
+Dwarf_Fde fde;
+Dwarf_Ptr fde_inst;
+Dwarf_Unsigned fde_instlen;
+Dwarf_Frame_Op *ops;
+Dwarf_Signed opcnt;
+Dwarf_Error de;
+
+/* ... assuming `dbg` references a valid DWARF debugging context,
+  `fde` references a valid FDE descriptor and `cie` holds the CIE
+  descriptor associated with the FDE descriptor ... */
+
+if (dwarf_get_fde_instr_bytes(fde, &fde_inst, &fde_instlen,
+    &de) != DW_DLV_OK)
+	errx(EXIT_FAILURE, "dwarf_get_fde_instr_bytes failed: %s",
+	    dwarf_errmsg(de));
+
+if (dwarf_expand_frame_instructions(cie, fde_inst, fde_instlen,
+    &ops, &opcnt, &de) != DW_DLV_OK)
+	errx(EXIT_FAILURE,
+	    "dwarf_expand_frame_instructions failed: %s",
+	    dwarf_errmsg(de));
+
+for (i = 0; i < opcnt; i++) {
+	/* ... use ops[i] ... */
+}
+
+/* Free the memory area when no longer needed. */
+dwarf_dealloc(dbg, ops, DW_DLA_FRAME_BLOCK);
+.Ed
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_frame_instructions_dealloc 3 ,
+.Xr dwarf_get_cie_info 3 ,
+.Xr dwarf_get_cie_index 3 ,
+.Xr dwarf_get_cie_of_fde ,
+.Xr dwarf_get_fde_at_pc 3 ,
+.Xr dwarf_get_fde_info_for_all_regs 3 ,
+.Xr dwarf_get_fde_info_for_all_regs3 3 ,
+.Xr dwarf_get_fde_info_for_cfa_reg3 3 ,
+.Xr dwarf_get_fde_info_for_reg 3 ,
+.Xr dwarf_get_fde_info_for_reg3 3 ,
+.Xr dwarf_get_fde_instr_bytes 3 ,
+.Xr dwarf_get_fde_list 3 ,
+.Xr dwarf_get_fde_list_eh 3 ,
+.Xr dwarf_get_fde_n 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_expr_current_offset.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,84 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_expr_current_offset.3 2073 2011-10-27 03:30:47Z jkoshy $
+.\"
+.Dd September 13, 2011
+.Os
+.Dt DWARF_EXPR_CURRENT_OFFSET 3
+.Sh NAME
+.Nm dwarf_expr_current_offset
+.Nd retrieve the number of bytes in a location expression stream
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "Dwarf_Unsigned"
+.Fo dwarf_expr_current_offset
+.Fa "Dwarf_P_Expr expr"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_expr_current_offset
+returns the size in bytes of the stream representation of a location
+expression.
+.Pp
+Argument
+.Ar expr
+should reference a location expression descriptor allocated using
+.Xr dwarf_new_expr 3 .
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_expr_current_offset
+returns the size in bytes of the location descriptor's stream
+representation.
+In case of an error, function
+.Fn dwarf_expr_current_offset
+returns
+.Dv DW_DLV_NOCOUNT
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_expr_current_offset
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Ar expr
+was NULL.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_expr_addr 3 ,
+.Xr dwarf_add_expr_addr_b 3 ,
+.Xr dwarf_add_expr_gen 3 ,
+.Xr dwarf_expr_into_block 3 ,
+.Xr dwarf_new_expr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_expr_into_block.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,94 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_expr_into_block.3 2073 2011-10-27 03:30:47Z jkoshy $
+.\"
+.Dd September 13, 2011
+.Os
+.Dt DWARF_EXPR_INTO_BLOCK 3
+.Sh NAME
+.Nm dwarf_expr_into_block
+.Nd retrieve the byte stream for a location expression
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "Dwarf_Addr"
+.Fo dwarf_expr_into_block
+.Fa "Dwarf_P_Expr expr"
+.Fa "Dwarf_Unsigned *length"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_expr_into_block
+retrieves the byte stream representation of a location expression.
+.Pp
+Argument
+.Ar expr
+should reference a location expression descriptor allocated using
+.Xr dwarf_new_expr 3 .
+.Pp
+Argument
+.Ar length
+should point to a location which will hold the size in bytes of
+the retrieved byte stream.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_expr_into_block
+returns the address of the first byte of the generated byte stream.
+In case of an error, function
+.Fn dwarf_expr_into_block
+returns
+.Dv DW_DLV_BADADDR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_expr_into_block
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar expr
+or
+.Ar length
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of
+the function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_AT_location_expr 3 ,
+.Xr dwarf_add_expr_addr 3 ,
+.Xr dwarf_add_expr_addr_b 3 ,
+.Xr dwarf_add_expr_gen 3 ,
+.Xr dwarf_expr_current_offset 3 ,
+.Xr dwarf_new_expr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_fde_cfa_offset.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,99 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_fde_cfa_offset.3 2073 2011-10-27 03:30:47Z jkoshy $
+.\"
+.Dd September 26, 2011
+.Os
+.Dt DWARF_FDE_CFA_OFFSET 3
+.Sh NAME
+.Nm dwarf_fde_cfa_offset
+.Nd add a DW_CFA_offset frame instruction to a DWARF frame descriptor
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "Dwarf_P_Fde"
+.Fo dwarf_fde_cfa_offset
+.Fa "Dwarf_P_Fde fde"
+.Fa "Dwarf_Unsigned reg"
+.Fa "Dwarf_Signed offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_fde_cfa_offset
+appends a
+.Dv DW_CFA_offset
+frame instruction to the frame descriptor referenced by argument
+.Ar fde .
+.Pp
+Argument
+.Ar fde
+should reference a frame descriptor allocated using
+.Xr dwarf_new_fde 3 .
+.Pp
+Argument
+.Ar reg
+specifies the register operand for the frame instruction.
+.Pp
+Argument
+.Ar offset
+specifies the offset operand for the frame instruction.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_fde_cfa_offset
+returns the frame descriptor given in argument
+.Ar fde .
+In case of an error, function
+.Fn dwarf_fde_cfa_offset
+returns
+.Dv DW_DLV_BADADDR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_fde_cfa_offset
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Ar fde
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_fde_inst 3 ,
+.Xr dwarf_add_frame_fde 3 ,
+.Xr dwarf_add_frame_fde_b 3 ,
+.Xr dwarf_add_frame_cie 3 ,
+.Xr dwarf_new_fde 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_find_macro_value_start.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,68 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_find_macro_value_start.3 2073 2011-10-27 03:30:47Z jkoshy $
+.\"
+.Dd March 26, 2011
+.Os
+.Dt DWARF_FIND_MACRO_VALUE_START 3
+.Sh NAME
+.Nm dwarf_find_macro_value_start
+.Nd return the address of the first byte of a macro value
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft char *
+.Fo dwarf_find_macro_value_start
+.Fa "char *macro_string"
+.Fc
+.Sh DESCRIPTION
+Given a DWARF macro string, function
+.Fn dwarf_find_macro_value_start
+returns a pointer to the first byte of the macro value part of the
+macro string.
+.Pp
+Argument
+.Ar macro_string
+should be a NUL-terminated string conforming to the macro format
+defined in the DWARF standard; see
+.Xr dwarf 4 .
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_find_macro_value_start
+returns a pointer to the first byte of the macro value.
+If the macro value part was not found, function
+.Fn dwarf_find_macro_value_start
+returns a pointer to the NUL-byte terminating argument
+.Ar macro_string .
+.Pp
+Function
+.Fn dwarf_find_macro_value_start
+returns NULL if argument
+.Ar macro_string
+was NULL.
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_macro_details 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_finish.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,140 @@
+.\" Copyright (c) 2009,2011 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: dwarf_finish.3 2122 2011-11-09 15:35:14Z jkoshy $
+.\"
+.Dd November 9, 2011
+.Os
+.Dt DWARF_FINISH 3
+.Sh NAME
+.Nm dwarf_finish ,
+.Nm dwarf_object_finish
+.Nd free resources associated with a debug descriptor
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fn dwarf_finish "Dwarf_Debug dbg" "Dwarf_Error *err"
+.Ft int
+.Fn dwarf_object_finish "Dwarf_Debug dbg" "Dwarf_Error *err"
+.Sh DESCRIPTION
+The
+.Fn dwarf_finish
+and
+.Fn dwarf_object_finish
+functions are used to release the resources associated with a debug
+descriptor allocated by a prior call to
+.Xr dwarf_init 3
+and
+.Xr dwarf_object_init 3
+respectively.
+.Pp
+Argument
+.Ar dbg
+denotes a valid
+.Vt Dwarf_Debug
+instance.
+Argument
+.Ar err
+will be used to record error information in case of an error.
+.Pp
+After a call to
+.Fn dwarf_finish
+or
+.Fn dwarf_object_finish ,
+the argument
+.Ar dbg
+will be invalid and should not be used further.
+.Pp
+For
+.Vt Dwarf_Debug
+descriptors opened using
+.Xr dwarf_init 3 ,
+the application would need to explicitly release the
+.Vt Elf
+instance associated with the descriptor by first retrieving
+the instance using
+.Xr dwarf_get_elf 3
+and closing it using
+.Xr elf_end 3 .
+.Sh RETURN VALUES
+These functions return
+.Dv DW_DLV_OK
+if successful.
+In case of an error, the functions return
+.Dv DW_DLV_ERROR
+and record additional information in argument
+.Ar err .
+.Sh EXAMPLES
+To deallocate a
+.Vt Dwarf_Debug
+instance allocated using
+.Xr dwarf_elf_init 3
+use:
+.Bd -literal -offset indent
+Dwarf_Debug dbg;
+Dwarf_Error de;
+
+if (dwarf_finish(dbg, &de) != DW_DLV_OK)
+	errx(EXIT_FAILURE, "dwarf_finish: %s", dwarf_errmsg(de));
+.Ed
+.Pp
+To deallocate a
+.Vt Dwarf_Debug
+instance allocated using
+.Xr dwarf_object_init 3
+use:
+.Bd -literal -offset indent
+Dwarf_Debug dbg;
+Dwarf_Error de;
+
+if (dwarf_object_finish(dbg, &de) != DW_DLV_OK)
+	errx(EXIT_FAILURE, "dwarf_object_finish: %s",
+	    dwarf_errmsg(de));
+.Ed
+.Pp
+To deallocate a
+.Vt Dwarf_Debug
+instance allocated using
+.Xr dwarf_init 3
+use:
+.Bd -literal -offset indent
+Dwarf_Debug dbg;
+Dward_Error de;
+Elf *e;
+
+if (dwarf_get_elf(dbg, &e, &de) != DW_DLV_OK)
+	errx(EXIT_FAILURE, "dwarf_get_elf: %s", dwarf_errmsg(&de));
+
+if (dwarf_finish(dbg, &de) != DW_DLV_OK)
+	errx(EXIT_FAILURE, "dwarf_finish: %s", dwarf_errmsg(de));
+
+(void) elf_end(e);
+.Ed
+.Sh SEE ALSO
+.Xr elf_end 3 ,
+.Xr dwarf_elf_init 3 ,
+.Xr dwarf_get_elf 3 ,
+.Xr dwarf_init 3 ,
+.Xr dwarf_object_init 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_finish.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_finish.c 2073 2011-10-27 03:30:47Z jkoshy $");
+
+int
+dwarf_finish(Dwarf_Debug dbg, Dwarf_Error *error)
+{
+	(void) error;	/* unused */
+
+	if (dbg == NULL)
+		return (DW_DLV_OK);
+
+	_dwarf_deinit(dbg);
+	_dwarf_elf_deinit(dbg);
+
+	free(dbg);
+
+	return (DW_DLV_OK);
+}
+
+
+int
+dwarf_object_finish(Dwarf_Debug dbg, Dwarf_Error *error)
+{
+	(void) error;	/* unused */
+
+	if (dbg == NULL)
+		return (DW_DLV_OK);
+
+	_dwarf_deinit(dbg);
+
+	free(dbg);
+
+	return (DW_DLV_OK);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_form.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,480 @@
+/*-
+ * Copyright (c) 2007 John Birrell (jb@freebsd.org)
+ * Copyright (c) 2009,2010 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_form.c 2073 2011-10-27 03:30:47Z jkoshy $");
+
+int
+dwarf_hasform(Dwarf_Attribute at, Dwarf_Half form, Dwarf_Bool *return_hasform,
+    Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+
+	dbg = at != NULL ? at->at_die->die_dbg : NULL;
+
+	if (at == NULL || return_hasform == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*return_hasform = (at->at_form == form);
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_whatform(Dwarf_Attribute at, Dwarf_Half *return_form, Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+
+	dbg = at != NULL ? at->at_die->die_dbg : NULL;
+
+	if (at == NULL || return_form == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*return_form = at->at_form;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_whatform_direct(Dwarf_Attribute at, Dwarf_Half *return_form,
+    Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+
+	dbg = at != NULL ? at->at_die->die_dbg : NULL;
+
+	if (at == NULL || return_form == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (at->at_indirect)
+		*return_form = DW_FORM_indirect;
+	else
+		*return_form = (Dwarf_Half) at->at_form;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_whatattr(Dwarf_Attribute at, Dwarf_Half *return_attr, Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+
+	dbg = at != NULL ? at->at_die->die_dbg : NULL;
+
+	if (at == NULL || return_attr == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*return_attr = (Dwarf_Half) at->at_attrib;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_formref(Dwarf_Attribute at, Dwarf_Off *return_offset, Dwarf_Error *error)
+{
+	int ret;
+	Dwarf_Debug dbg;
+
+	dbg = at != NULL ? at->at_die->die_dbg : NULL;
+
+	if (at == NULL || return_offset == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	switch (at->at_form) {
+	case DW_FORM_ref1:
+	case DW_FORM_ref2:
+	case DW_FORM_ref4:
+	case DW_FORM_ref8:
+	case DW_FORM_ref_udata:
+		*return_offset = (Dwarf_Off) at->u[0].u64;
+		ret = DW_DLV_OK;
+		break;
+	default:
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
+		ret = DW_DLV_ERROR;
+	}
+
+	return (ret);
+}
+
+int
+dwarf_global_formref(Dwarf_Attribute at, Dwarf_Off *return_offset,
+    Dwarf_Error *error)
+{
+	int ret;
+	Dwarf_Debug dbg;
+
+	dbg = at != NULL ? at->at_die->die_dbg : NULL;
+
+	if (at == NULL || return_offset == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	switch (at->at_form) {
+	case DW_FORM_ref_addr:
+	case DW_FORM_sec_offset:
+		*return_offset = (Dwarf_Off) at->u[0].u64;
+		ret = DW_DLV_OK;
+		break;
+	case DW_FORM_ref1:
+	case DW_FORM_ref2:
+	case DW_FORM_ref4:
+	case DW_FORM_ref8:
+	case DW_FORM_ref_udata:
+		*return_offset = (Dwarf_Off) at->u[0].u64 +
+			at->at_die->die_cu->cu_offset;
+		ret = DW_DLV_OK;
+		break;
+	default:
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
+		ret = DW_DLV_ERROR;
+	}
+
+	return (ret);
+}
+
+int
+dwarf_formaddr(Dwarf_Attribute at, Dwarf_Addr *return_addr, Dwarf_Error *error)
+{
+	int ret;
+	Dwarf_Debug dbg;
+
+	dbg = at != NULL ? at->at_die->die_dbg : NULL;
+
+	if (at == NULL || return_addr == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (at->at_form == DW_FORM_addr) {
+		*return_addr = at->u[0].u64;
+		ret = DW_DLV_OK;
+	} else {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
+		ret = DW_DLV_ERROR;
+	}
+
+	return (ret);
+}
+
+int
+dwarf_formflag(Dwarf_Attribute at, Dwarf_Bool *return_bool, Dwarf_Error *error)
+{
+	int ret;
+	Dwarf_Debug dbg;
+
+	dbg = at != NULL ? at->at_die->die_dbg : NULL;
+
+	if (at == NULL || return_bool == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (at->at_form == DW_FORM_flag ||
+	    at->at_form == DW_FORM_flag_present) {
+		*return_bool = (Dwarf_Bool) (!!at->u[0].u64);
+		ret = DW_DLV_OK;
+	} else {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
+		ret = DW_DLV_ERROR;
+	}
+
+	return (ret);
+}
+
+int
+dwarf_formudata(Dwarf_Attribute at, Dwarf_Unsigned *return_uvalue,
+    Dwarf_Error *error)
+{
+	int ret;
+	Dwarf_Debug dbg;
+
+	dbg = at != NULL ? at->at_die->die_dbg : NULL;
+
+	if (at == NULL || return_uvalue == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	switch (at->at_form) {
+	case DW_FORM_data1:
+	case DW_FORM_data2:
+	case DW_FORM_data4:
+	case DW_FORM_data8:
+	case DW_FORM_udata:
+		*return_uvalue = at->u[0].u64;
+		ret = DW_DLV_OK;
+		break;
+	default:
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
+		ret = DW_DLV_ERROR;
+	}
+
+	return (ret);
+}
+
+int
+dwarf_formsdata(Dwarf_Attribute at, Dwarf_Signed *return_svalue,
+    Dwarf_Error *error)
+{
+	int ret;
+	Dwarf_Debug dbg;
+
+	dbg = at != NULL ? at->at_die->die_dbg : NULL;
+
+	if (at == NULL || return_svalue == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	switch (at->at_form) {
+	case DW_FORM_data1:
+		*return_svalue = (int8_t) at->u[0].s64;
+		ret = DW_DLV_OK;
+		break;
+	case DW_FORM_data2:
+		*return_svalue = (int16_t) at->u[0].s64;
+		ret = DW_DLV_OK;
+		break;
+	case DW_FORM_data4:
+		*return_svalue = (int32_t) at->u[0].s64;
+		ret = DW_DLV_OK;
+		break;
+	case DW_FORM_data8:
+	case DW_FORM_sdata:
+		*return_svalue = at->u[0].s64;
+		ret = DW_DLV_OK;
+		break;
+	default:
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
+		ret = DW_DLV_ERROR;
+	}
+
+	return (ret);
+}
+
+int
+dwarf_formblock(Dwarf_Attribute at, Dwarf_Block **return_block,
+    Dwarf_Error *error)
+{
+	int ret;
+	Dwarf_Debug dbg;
+
+	dbg = at != NULL ? at->at_die->die_dbg : NULL;
+
+	if (at == NULL || return_block == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	switch (at->at_form) {
+	case DW_FORM_block:
+	case DW_FORM_block1:
+	case DW_FORM_block2:
+	case DW_FORM_block4:
+		*return_block = &at->at_block;
+		ret = DW_DLV_OK;
+		break;
+	default:
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
+		ret = DW_DLV_ERROR;
+	}
+
+	return (ret);
+}
+
+int
+dwarf_formsig8(Dwarf_Attribute at, Dwarf_Sig8 *return_sig8, Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+
+	dbg = at != NULL ? at->at_die->die_dbg : NULL;
+
+	if (at == NULL || return_sig8 == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+	
+	if (at->at_form != DW_FORM_ref_sig8) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
+		return (DW_DLV_ERROR);
+	}
+
+	assert(at->u[0].u64 == 8);
+	memcpy(return_sig8->signature, at->u[1].u8p, at->u[0].u64);
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_formexprloc(Dwarf_Attribute at, Dwarf_Unsigned *return_exprlen,
+    Dwarf_Ptr *return_expr, Dwarf_Error *error)
+{
+
+	Dwarf_Debug dbg;
+
+	dbg = at != NULL ? at->at_die->die_dbg : NULL;
+
+	if (at == NULL || return_exprlen == NULL || return_expr == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (at->at_form != DW_FORM_exprloc) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
+		return (DW_DLV_ERROR);
+	}
+
+	*return_exprlen = at->u[0].u64;
+	*return_expr = (void *) at->u[1].u8p;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_formstring(Dwarf_Attribute at, char **return_string,
+    Dwarf_Error *error)
+{
+	int ret;
+	Dwarf_Debug dbg;
+
+	dbg = at != NULL ? at->at_die->die_dbg : NULL;
+
+	if (at == NULL || return_string == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	switch (at->at_form) {
+	case DW_FORM_string:
+		*return_string = (char *) at->u[0].s;
+		ret = DW_DLV_OK;
+		break;
+	case DW_FORM_strp:
+		*return_string = (char *) at->u[1].s;
+		ret = DW_DLV_OK;
+		break;
+	default:
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
+		ret = DW_DLV_ERROR;
+	}
+
+	return (ret);
+}
+
+enum Dwarf_Form_Class
+dwarf_get_form_class(Dwarf_Half dwversion, Dwarf_Half attr,
+    Dwarf_Half offset_size, Dwarf_Half form)
+{
+
+	switch (form) {
+	case DW_FORM_addr:
+		return (DW_FORM_CLASS_ADDRESS);
+	case DW_FORM_block:
+	case DW_FORM_block1:
+	case DW_FORM_block2:
+	case DW_FORM_block4:
+		return (DW_FORM_CLASS_BLOCK);
+	case DW_FORM_string:
+	case DW_FORM_strp:
+		return (DW_FORM_CLASS_STRING);
+	case DW_FORM_flag:
+	case DW_FORM_flag_present:
+		return (DW_FORM_CLASS_FLAG);
+	case DW_FORM_ref_addr:
+	case DW_FORM_ref_sig8:
+	case DW_FORM_ref_udata:
+	case DW_FORM_ref1:
+	case DW_FORM_ref2:
+	case DW_FORM_ref4:
+	case DW_FORM_ref8:
+		return (DW_FORM_CLASS_REFERENCE);
+	case DW_FORM_exprloc:
+		return (DW_FORM_CLASS_EXPRLOC);
+	case DW_FORM_data1:
+	case DW_FORM_data2:
+	case DW_FORM_sdata:
+	case DW_FORM_udata:
+		return (DW_FORM_CLASS_CONSTANT);
+	case DW_FORM_data4:
+	case DW_FORM_data8:
+		if (dwversion > 3)
+			return (DW_FORM_CLASS_CONSTANT);
+		if (form == DW_FORM_data4 && offset_size != 4)
+			return (DW_FORM_CLASS_CONSTANT);
+		if (form == DW_FORM_data8 && offset_size != 8)
+			return (DW_FORM_CLASS_CONSTANT);
+		/* FALLTHROUGH */
+	case DW_FORM_sec_offset:
+		/*
+		 * DW_FORM_data4 and DW_FORM_data8 can be used as
+		 * offset/pointer before DWARF4. Newly added
+		 * DWARF4 form DW_FORM_sec_offset intents to replace
+		 * DW_FORM_data{4,8} for this purpose. Anyway, to
+		 * determine the actual class for these forms, we need
+		 * to also look at the attribute number.
+		 */
+		switch (attr) {
+		case DW_AT_location:
+		case DW_AT_string_length:
+		case DW_AT_return_addr:
+		case DW_AT_data_member_location:
+		case DW_AT_frame_base:
+		case DW_AT_segment:
+		case DW_AT_static_link:
+		case DW_AT_use_location:
+		case DW_AT_vtable_elem_location:
+			return (DW_FORM_CLASS_LOCLISTPTR);
+		case DW_AT_stmt_list:
+			return (DW_FORM_CLASS_LINEPTR);
+		case DW_AT_start_scope:
+		case DW_AT_ranges:
+			return (DW_FORM_CLASS_RANGELISTPTR);
+		case DW_AT_macro_info:
+			return (DW_FORM_CLASS_MACPTR);
+		default:
+			if (form == DW_FORM_data4 || form == DW_FORM_data8)
+				return (DW_FORM_CLASS_CONSTANT);
+			else
+				return (DW_FORM_CLASS_UNKNOWN);
+		}
+	default:
+		return (DW_FORM_CLASS_UNKNOWN);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_formaddr.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,97 @@
+.\" Copyright (c) 2010 Joseph Koshy
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_formaddr.3 2073 2011-10-27 03:30:47Z jkoshy $
+.\"
+.Dd July 23, 2010
+.Os
+.Dt DWARF_FORMADDR 3
+.Sh NAME
+.Nm dwarf_formaddr
+.Nd return the value of an ADDRESS class attribute
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_formaddr
+.Fa "Dwarf_Attribute attr"
+.Fa "Dwarf_Addr *ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_formaddr
+sets the location pointed to by argument
+.Ar ret
+to the address represented by the attribute referenced
+by argument
+.Ar attr .
+The form of argument
+.Ar attr
+must be
+.Dv DW_FORM_addr .
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to return an error descriptor in case
+of an error.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_formaddr
+returns
+.Dv DW_DLV_OK
+on success.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_formblock
+may fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_ATTR_FORM_BAD"
+.It Bq Er DW_DLE_ARGUMENT
+Either of arguments
+.Ar attr
+or
+.Ar ret
+was NULL.
+.It Bq Er DW_DLE_ATTR_FORM_BAD
+The attribute referenced by argument
+.Ar attr
+was not of form
+.Dv DW_FORM_addr .
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_attr 3 ,
+.Xr dwarf_formblock 3 ,
+.Xr dwarf_formflag 3 ,
+.Xr dwarf_formref 3 ,
+.Xr dwarf_formsdata 3 ,
+.Xr dwarf_formsig8 3 ,
+.Xr dwarf_formstring 3 ,
+.Xr dwarf_formudata 3 ,
+.Xr dwarf_hasattr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_formblock.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,109 @@
+.\" Copyright (c) 2010 Joseph Koshy
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_formblock.3 3182 2015-04-10 16:08:10Z emaste $
+.\"
+.Dd July 23, 2010
+.Os
+.Dt DWARF_FORMBLOCK 3
+.Sh NAME
+.Nm dwarf_formblock
+.Nd return the value of a BLOCK attribute
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_formblock
+.Fa "Dwarf_Attribute attr"
+.Fa "Dwarf_Block **ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_formblock
+sets the location pointed to by argument
+.Ar ret
+to a pointer to a
+.Vt Dwarf_Block
+structure containing the value of the attribute referenced
+by argument
+.Ar attr .
+The form of argument
+.Ar attr
+must be one of
+.Dv DW_FORM_block ,
+.Dv DW_FORM_block1 ,
+.Dv DW_FORM_block2
+or
+.Dv DW_FORM_block4 .
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to return an error descriptor in case
+of an error.
+.Ss Memory Management
+The memory area referenced by the returned pointer is managed by
+the DWARF(3) library.
+The application should not attempt to free this memory
+area.
+Portable code may indicate that the memory area is to be freed by
+using
+.Xr dwarf_dealloc 3 .
+.Sh RETURN VALUES
+Function
+.Fn dwarf_formblock
+returns
+.Dv DW_DLV_OK
+on success.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_formblock
+may fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_ATTR_FORM_BAD"
+.It Bq Er DW_DLE_ARGUMENT
+Either of arguments
+.Ar attr
+or
+.Ar ret
+was NULL.
+.It Bq Er DW_DLE_ATTR_FORM_BAD
+The attribute referenced by argument
+.Ar attr
+was not of a permitted kind.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_attr 3 ,
+.Xr dwarf_formflag 3 ,
+.Xr dwarf_formref 3 ,
+.Xr dwarf_formsdata 3 ,
+.Xr dwarf_formsig8 3 ,
+.Xr dwarf_formstring 3 ,
+.Xr dwarf_formudata 3 ,
+.Xr dwarf_hasattr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_formexprloc.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,109 @@
+.\" Copyright (c) 2010 Joseph Koshy
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_formexprloc.3 2073 2011-10-27 03:30:47Z jkoshy $
+.\"
+.Dd July 25, 2010
+.Os
+.Dt DWARF_FORMEXPRLOC 3
+.Sh NAME
+.Nm dwarf_formexprloc
+.Nd return information about a location expression
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_formexprloc
+.Fa "Dwarf_Attribute attr"
+.Fa "Dwarf_Unsigned *retlen"
+.Fa "Dwarf_Ptr *retexpr"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_formexprloc
+allows an application to retrieve the length and the bytes of a
+DWARF location expression.
+.Pp
+Argument
+.Ar attr
+should reference a DWARF attribute of the form
+.Dv DW_FORM_exprloc .
+Argument
+.Ar retlen
+should point to a location that will be set to the length of the
+location expression.
+Argument
+.Ar retexpr
+should point to a location that will be set to a pointer to the
+content of the location expression itself.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to return an error descriptor in case
+of an error.
+.Ss Memory Management
+The application should not attempt to free the memory
+area referenced by the pointer returned in argument
+.Ar retexpr .
+.Sh RETURN VALUES
+Function
+.Fn dwarf_formexprloc
+returns
+.Dv DW_DLV_OK
+on success.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_formexprloc
+may fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_ATTR_FORM_BAD"
+.It Bq Er DW_DLE_ARGUMENT
+One of arguments
+.Ar attr ,
+.Ar retlen
+or
+.Ar retexpr
+was NULL.
+.It Bq Er DW_DLE_ATTR_FORM_BAD
+The attribute referenced by argument
+.Ar attr
+was not of form
+.Dv DW_FORM_exprloc .
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_attr 3 ,
+.Xr dwarf_formblock 3 ,
+.Xr dwarf_formflag 3 ,
+.Xr dwarf_formref 3 ,
+.Xr dwarf_formsdata 3 ,
+.Xr dwarf_formsig8 3 ,
+.Xr dwarf_formstring 3 ,
+.Xr dwarf_formudata 3 ,
+.Xr dwarf_hasattr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_formflag.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,97 @@
+.\" Copyright (c) 2010 Joseph Koshy
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_formflag.3 3181 2015-04-10 13:22:51Z emaste $
+.\"
+.Dd June 21, 2010
+.Os
+.Dt DWARF_FORMFLAG 3
+.Sh NAME
+.Nm dwarf_formflag
+.Nd return the value of a BOOLEAN class attribute
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_formflag
+.Fa "Dwarf_Attribute attr"
+.Fa "Dwarf_Bool *ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_formflag
+sets the location pointed to by argument
+.Ar ret
+to 1 if the attribute referenced by argument
+.Ar attr
+has a non-zero value, or 0 otherwise.
+The form of argument
+.Ar attr
+must be one of
+.Dv DW_FORM_flag
+or
+.Dv DW_FORM_flag_present .
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to return an error descriptor in case
+of an error.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_formflag
+returns
+.Dv DW_DLV_OK
+on success.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_formflag
+may fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_ATTR_FORM_BAD"
+.It Bq Er DW_DLE_ARGUMENT
+Either of arguments
+.Ar attr
+or
+.Ar ret
+was NULL.
+.It Bq Er DW_DLE_ATTR_FORM_BAD
+The attribute referenced by argument
+.Ar attr
+was not of a permitted kind.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_attr 3 ,
+.Xr dwarf_formblock 3 ,
+.Xr dwarf_formref 3 ,
+.Xr dwarf_formsdata 3 ,
+.Xr dwarf_formsig8 3 ,
+.Xr dwarf_formstring 3 ,
+.Xr dwarf_formudata 3 ,
+.Xr dwarf_hasattr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_formref.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,136 @@
+.\" Copyright (c) 2010 Joseph Koshy
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_formref.3 3181 2015-04-10 13:22:51Z emaste $
+.\"
+.Dd June 21, 2010
+.Os
+.Dt DWARF_FORMREF 3
+.Sh NAME
+.Nm dwarf_formref ,
+.Nm dwarf_global_formref
+.Nd retrieve offsets for REFERENCE class attributes
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_formref
+.Fa "Dwarf_Attribute attr"
+.Fa "Dwarf_Off *retoffset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_global_formref
+.Fa "Dwarf_Attribute attr"
+.Fa "Dwarf_Off *retoffset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+These functions return the offsets associated with a DWARF attribute
+descriptor.
+.Pp
+Function
+.Fn dwarf_formref
+returns the compilation unit relative offset of the descriptor
+referenced by argument
+.Ar attr
+in the location pointed to by argument
+.Ar retoffset .
+Argument
+.Ar attr
+must be a reference that is local to a compilation unit.
+Permitted forms for argument
+.Ar attr
+are
+.Dv DW_FORM_ref1 ,
+.Dv DW_FORM_ref2 ,
+.Dv DW_FORM_ref4 ,
+.Dv DW_FORM_ref8
+and
+.Dv DW_FORM_ref_udata .
+.Pp
+Function
+.Fn dwarf_global_formref
+returns the section-relative offset of the descriptor referenced by
+argument
+.Ar attr
+in the location pointed to by argument
+.Ar retoffset .
+Argument
+.Ar attr
+should be a legal
+.Sy REFERENCE
+class form.
+Permitted forms for argument
+.Ar attr
+are:
+.Dv DW_FORM_ref_addr ,
+.Dv DW_FORM_ref_udata ,
+.Dv DW_FORM_ref1 ,
+.Dv DW_FORM_ref2 ,
+.Dv DW_FORM_ref4 ,
+.Dv DW_FORM_ref8
+and
+.Dv DW_FORM_sec_offset .
+The returned offset is relative to the start of the
+.Dq .debug_info
+ELF section.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to return an error descriptor in case
+of an error.
+.Sh RETURN VALUES
+These functions return
+.Dv DW_DLV_OK
+on success.
+In case of an error, these functions return
+.Dv DW_DLV_ERROR
+and sets argument
+.Ar err .
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_ATTR_FORM_BAD"
+.It Bq Er DW_DLE_ARGUMENT
+Either of arguments
+.Ar attr
+or
+.Ar retoffset
+was NULL.
+.It Bq Er DW_DLE_ATTR_FORM_BAD
+The attribute referenced by argument
+.Ar attr
+was not of a permitted kind.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_attr 3 ,
+.Xr dwarf_formblock 3 ,
+.Xr dwarf_formflag 3 ,
+.Xr dwarf_formsdata 3 ,
+.Xr dwarf_formsig8 3 ,
+.Xr dwarf_formstring 3 ,
+.Xr dwarf_formudata 3 ,
+.Xr dwarf_hasattr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_formsig8.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,96 @@
+.\" Copyright (c) 2010 Joseph Koshy
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_formsig8.3 3181 2015-04-10 13:22:51Z emaste $
+.\"
+.Dd July 24, 2010
+.Os
+.Dt DWARF_FORMSIG8 3
+.Sh NAME
+.Nm dwarf_formsig8
+.Nd return the 64-bit type signature for a DWARF type
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_formsig8
+.Fa "Dwarf_Attribute attr"
+.Fa "Dwarf_Sig8 *ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_formsig8
+sets the location pointed to by argument
+.Ar ret
+to the 64-bit type signature that is the value of
+the attribute referenced by argument
+.Ar attr .
+The form of argument
+.Ar attr
+must be
+.Dv DW_FORM_ref_sig8 .
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to return an error descriptor in case
+of an error.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_formsig8
+returns
+.Dv DW_DLV_OK
+on success.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_formsig8
+may fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_ATTR_FORM_BAD"
+.It Bq Er DW_DLE_ARGUMENT
+Either of arguments
+.Ar attr
+or
+.Ar ret
+was NULL.
+.It Bq Er DW_DLE_ATTR_FORM_BAD
+The attribute referenced by argument
+.Ar attr
+was not of a permitted kind.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_attr 3 ,
+.Xr dwarf_formflag 3 ,
+.Xr dwarf_formref 3 ,
+.Xr dwarf_formsdata 3 ,
+.Xr dwarf_formstring 3 ,
+.Xr dwarf_formudata 3 ,
+.Xr dwarf_hasattr 3
+.Sh HISTORY
+Type signatures were added in version 4 of the DWARF specification.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_formstring.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,101 @@
+.\" Copyright (c) 2010 Joseph Koshy
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_formstring.3 2073 2011-10-27 03:30:47Z jkoshy $
+.\"
+.Dd July 24, 2010
+.Os
+.Dt DWARF_FORMSTRING 3
+.Sh NAME
+.Nm dwarf_formstring
+.Nd return the value of a STRING class attribute
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_formstring
+.Fa "Dwarf_Attribute attr"
+.Fa "char **ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_formstring
+sets the location pointed to by argument
+.Ar ret
+to a pointer to a NUL-terminated string containing
+the value of the attribute referenced by argument
+.Ar attr .
+The form of argument
+.Ar attr
+must be one of
+.Dv DW_FORM_string
+or
+.Dv DW_FORM_strp .
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to return an error descriptor in case
+of an error.
+.Ss Memory Management
+The memory area referenced by the returned pointer is managed by
+the DWARF(3) library.
+The application should not attempt to directly free this memory
+area.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_formstring
+returns
+.Dv DW_DLV_OK
+on success.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_formstring
+may fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_ATTR_FORM_BAD"
+.It Bq Er DW_DLE_ARGUMENT
+Either of arguments
+.Ar attr
+or
+.Ar ret
+was NULL.
+.It Bq Er DW_DLE_ATTR_FORM_BAD
+The attribute referenced by argument
+.Ar attr
+was not of a permitted kind.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_attr 3 ,
+.Xr dwarf_formblock 3 ,
+.Xr dwarf_formref 3 ,
+.Xr dwarf_formsdata 3 ,
+.Xr dwarf_formsig8 3 ,
+.Xr dwarf_formudata 3 ,
+.Xr dwarf_hasattr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_formudata.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,122 @@
+.\" Copyright (c) 2010 Joseph Koshy
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_formudata.3 3181 2015-04-10 13:22:51Z emaste $
+.\"
+.Dd June 21, 2010
+.Os
+.Dt DWARF_FORMUDATA 3
+.Sh NAME
+.Nm dwarf_formudata ,
+.Nm dwarf_formsdata
+.Nd return the value of a CONSTANT class attribute
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_formudata
+.Fa "Dwarf_Attribute attr"
+.Fa "Dwarf_Unsigned *ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_formsdata
+.Fa "Dwarf_Attribute attr"
+.Fa "Dwarf_Signed *ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+These functions return the value associated with a DWARF attribute
+describing a constant.
+.Pp
+Function
+.Fn dwarf_formudata
+sets the location pointed to by argument
+.Ar ret
+to the value of the attribute referenced by argument
+.Ar attr ,
+treating the value as an unsigned quantity.
+Argument
+.Ar attr
+must have one of the following forms:
+.Dv DW_FORM_data1 ,
+.Dv DW_FORM_data2 ,
+.Dv DW_FORM_data4 ,
+.Dv DW_FORM_data8
+and
+.Dv DW_FORM_udata .
+.Pp
+Function
+.Fn dwarf_formsdata
+sets the location pointed to by argument
+.Ar ret
+to the value of the attribute referenced by argument
+.Ar attr ,
+appropriately sign extended.
+Argument
+.Ar attr
+must have one of the following forms:
+.Dv DW_FORM_data1 ,
+.Dv DW_FORM_data2 ,
+.Dv DW_FORM_data4 ,
+.Dv DW_FORM_data8
+and
+.Dv DW_FORM_sdata .
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to return an error descriptor in case
+of an error.
+.Sh RETURN VALUES
+These functions return
+.Dv DW_DLV_OK
+on success.
+In case of an error, they return
+.Dv DW_DLV_ERROR
+and set argument
+.Ar err .
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_ATTR_FORM_BAD"
+.It Bq Er DW_DLE_ARGUMENT
+Either of arguments
+.Ar attr
+or
+.Ar ret
+was NULL.
+.It Bq Er DW_DLE_ATTR_FORM_BAD
+The attribute referenced by argument
+.Ar attr
+was not of a permitted kind.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_attr 3 ,
+.Xr dwarf_formblock 3 ,
+.Xr dwarf_formflag 3 ,
+.Xr dwarf_formref 3 ,
+.Xr dwarf_formsig8 3 ,
+.Xr dwarf_formstring 3 ,
+.Xr dwarf_hasattr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_frame.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,603 @@
+/*-
+ * Copyright (c) 2009,2011 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_frame.c 3106 2014-12-19 16:00:58Z kaiwang27 $");
+
+int
+dwarf_get_fde_list(Dwarf_Debug dbg, Dwarf_Cie **cie_list,
+    Dwarf_Signed *cie_count, Dwarf_Fde **fde_list, Dwarf_Signed *fde_count,
+    Dwarf_Error *error)
+{
+
+	if (dbg == NULL || cie_list == NULL || cie_count == NULL ||
+	    fde_list == NULL || fde_count == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (dbg->dbg_internal_reg_table == NULL) {
+		if (_dwarf_frame_interal_table_init(dbg, error) != DW_DLE_NONE)
+			return (DW_DLV_ERROR);
+	}
+
+	if (dbg->dbg_frame == NULL) {
+		if (_dwarf_frame_section_load(dbg, error) != DW_DLE_NONE)
+			return (DW_DLV_ERROR);
+		if (dbg->dbg_frame == NULL) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+			return (DW_DLV_NO_ENTRY);
+		}
+	}
+
+	if (dbg->dbg_frame->fs_ciearray == NULL ||
+	    dbg->dbg_frame->fs_fdearray == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	*cie_list = dbg->dbg_frame->fs_ciearray;
+	*cie_count = dbg->dbg_frame->fs_cielen;
+	*fde_list = dbg->dbg_frame->fs_fdearray;
+	*fde_count = dbg->dbg_frame->fs_fdelen;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_fde_list_eh(Dwarf_Debug dbg, Dwarf_Cie **cie_list,
+    Dwarf_Signed *cie_count, Dwarf_Fde **fde_list, Dwarf_Signed *fde_count,
+    Dwarf_Error *error)
+{
+
+	if (dbg == NULL || cie_list == NULL || cie_count == NULL ||
+	    fde_list == NULL || fde_count == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (dbg->dbg_internal_reg_table == NULL) {
+		if (_dwarf_frame_interal_table_init(dbg, error) != DW_DLE_NONE)
+			return (DW_DLV_ERROR);
+	}
+
+	if (dbg->dbg_eh_frame == NULL) {
+		if (_dwarf_frame_section_load_eh(dbg, error) != DW_DLE_NONE)
+			return (DW_DLV_ERROR);
+		if (dbg->dbg_eh_frame == NULL) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+			return (DW_DLV_NO_ENTRY);
+		}
+	}
+
+	if (dbg->dbg_eh_frame->fs_ciearray == NULL ||
+	    dbg->dbg_eh_frame->fs_fdearray == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	*cie_list = dbg->dbg_eh_frame->fs_ciearray;
+	*cie_count = dbg->dbg_eh_frame->fs_cielen;
+	*fde_list = dbg->dbg_eh_frame->fs_fdearray;
+	*fde_count = dbg->dbg_eh_frame->fs_fdelen;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_fde_n(Dwarf_Fde *fdelist, Dwarf_Unsigned fde_index,
+    Dwarf_Fde *ret_fde, Dwarf_Error *error)
+{
+	Dwarf_FrameSec fs;
+	Dwarf_Debug dbg;
+
+	dbg = fdelist != NULL ? (*fdelist)->fde_dbg : NULL;
+
+	if (fdelist == NULL || ret_fde == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	fs = fdelist[0]->fde_fs;
+	assert(fs != NULL);
+
+	if (fde_index >= fs->fs_fdelen) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	*ret_fde = fdelist[fde_index];
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_fde_at_pc(Dwarf_Fde *fdelist, Dwarf_Addr pc, Dwarf_Fde *ret_fde,
+    Dwarf_Addr *lopc, Dwarf_Addr *hipc, Dwarf_Error *error)
+{
+	Dwarf_FrameSec fs;
+	Dwarf_Debug dbg;
+	Dwarf_Fde fde;
+	int i;
+
+	dbg = fdelist != NULL ? (*fdelist)->fde_dbg : NULL;
+
+	if (fdelist == NULL || ret_fde == NULL || lopc == NULL ||
+	    hipc == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	fs = fdelist[0]->fde_fs;
+	assert(fs != NULL);
+
+	for (i = 0; (Dwarf_Unsigned)i < fs->fs_fdelen; i++) {
+		fde = fdelist[i];
+		if (pc >= fde->fde_initloc && pc < fde->fde_initloc +
+		    fde->fde_adrange) {
+			*ret_fde = fde;
+			*lopc = fde->fde_initloc;
+			*hipc = fde->fde_initloc + fde->fde_adrange - 1;
+			return (DW_DLV_OK);
+		}
+	}
+
+	DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+	return (DW_DLV_NO_ENTRY);
+}
+
+int
+dwarf_get_cie_of_fde(Dwarf_Fde fde, Dwarf_Cie *ret_cie, Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+
+	dbg = fde != NULL ? fde->fde_dbg : NULL;
+
+	if (fde == NULL || ret_cie == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*ret_cie = fde->fde_cie;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_fde_range(Dwarf_Fde fde, Dwarf_Addr *low_pc, Dwarf_Unsigned *func_len,
+    Dwarf_Ptr *fde_bytes, Dwarf_Unsigned *fde_byte_len, Dwarf_Off *cie_offset,
+    Dwarf_Signed *cie_index, Dwarf_Off *fde_offset, Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+
+	dbg = fde != NULL ? fde->fde_dbg : NULL;
+
+	if (fde == NULL || low_pc == NULL || func_len == NULL ||
+	    fde_bytes == NULL || fde_byte_len == NULL || cie_offset == NULL ||
+	    cie_index == NULL || fde_offset == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*low_pc = fde->fde_initloc;
+	*func_len = fde->fde_adrange;
+	*fde_bytes = fde->fde_addr;
+	*fde_byte_len = fde->fde_length;
+	*cie_offset = fde->fde_cieoff;
+	*cie_index = fde->fde_cie->cie_index;
+	*fde_offset = fde->fde_offset;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_cie_info(Dwarf_Cie cie, Dwarf_Unsigned *bytes_in_cie,
+    Dwarf_Small *version, char **augmenter, Dwarf_Unsigned *caf,
+    Dwarf_Unsigned *daf, Dwarf_Half *ra, Dwarf_Ptr *initinst,
+    Dwarf_Unsigned *inst_len, Dwarf_Error *error)
+{
+
+	if (cie == NULL || bytes_in_cie == NULL || version == NULL ||
+	    augmenter == NULL || caf == NULL || daf == NULL || ra == NULL ||
+	    initinst == NULL || inst_len == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*bytes_in_cie = cie->cie_length;
+	*version = cie->cie_version;
+	*augmenter = (char *) cie->cie_augment;
+	*caf = cie->cie_caf;
+	*daf = cie->cie_daf;
+	*ra = cie->cie_ra;
+	*initinst = cie->cie_initinst;
+	*inst_len = cie->cie_instlen;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_cie_index(Dwarf_Cie cie, Dwarf_Signed *cie_index, Dwarf_Error *error)
+{
+
+	if (cie == NULL || cie_index == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*cie_index = cie->cie_index;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_fde_instr_bytes(Dwarf_Fde fde, Dwarf_Ptr *ret_inst,
+    Dwarf_Unsigned *ret_len, Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+
+	dbg = fde != NULL ? fde->fde_dbg : NULL;
+
+	if (fde == NULL || ret_inst == NULL || ret_len == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*ret_inst = fde->fde_inst;
+	*ret_len = fde->fde_instlen;
+
+	return (DW_DLV_OK);
+}
+
+#define	RL	rt->rt3_rules[table_column]
+#define	CFA	rt->rt3_cfa_rule
+
+int
+dwarf_get_fde_info_for_reg(Dwarf_Fde fde, Dwarf_Half table_column,
+    Dwarf_Addr pc_requested, Dwarf_Signed *offset_relevant,
+    Dwarf_Signed *register_num, Dwarf_Signed *offset, Dwarf_Addr *row_pc,
+    Dwarf_Error *error)
+{
+	Dwarf_Regtable3 *rt;
+	Dwarf_Debug dbg;
+	Dwarf_Addr pc;
+	int ret;
+
+	dbg = fde != NULL ? fde->fde_dbg : NULL;
+
+	if (fde == NULL || offset_relevant == NULL || register_num == NULL ||
+	    offset == NULL || row_pc == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (pc_requested < fde->fde_initloc ||
+	    pc_requested >= fde->fde_initloc + fde->fde_adrange) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
+		return (DW_DLV_ERROR);
+	}
+
+	ret = _dwarf_frame_get_internal_table(fde, pc_requested, &rt, &pc,
+	    error);
+	if (ret != DW_DLE_NONE)
+		return (DW_DLV_ERROR);
+
+	if (table_column == dbg->dbg_frame_cfa_value) {
+		/* Application ask for CFA. */
+		*offset_relevant = CFA.dw_offset_relevant;
+		*register_num = CFA.dw_regnum;
+		*offset = CFA.dw_offset_or_block_len;
+	} else {
+		/* Application ask for normal registers. */
+		if (table_column >= dbg->dbg_frame_rule_table_size ||
+		    table_column >= DW_REG_TABLE_SIZE) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_FRAME_TABLE_COL_BAD);
+			return (DW_DLV_ERROR);
+		}
+
+		*offset_relevant = RL.dw_offset_relevant;
+		*register_num = RL.dw_regnum;
+		*offset = RL.dw_offset_or_block_len;
+	}
+
+	*row_pc = pc;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_fde_info_for_all_regs(Dwarf_Fde fde, Dwarf_Addr pc_requested,
+    Dwarf_Regtable *reg_table, Dwarf_Addr *row_pc, Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+	Dwarf_Regtable3 *rt;
+	Dwarf_Addr pc;
+	Dwarf_Half cfa;
+	int i, ret;
+
+	dbg = fde != NULL ? fde->fde_dbg : NULL;
+
+	if (fde == NULL || reg_table == NULL || row_pc == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	assert(dbg != NULL);
+
+	if (pc_requested < fde->fde_initloc ||
+	    pc_requested >= fde->fde_initloc + fde->fde_adrange) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
+		return (DW_DLV_ERROR);
+	}
+
+	ret = _dwarf_frame_get_internal_table(fde, pc_requested, &rt, &pc,
+	    error);
+	if (ret != DW_DLE_NONE)
+		return (DW_DLV_ERROR);
+
+	/*
+	 * Copy the CFA rule to the column intended for holding the CFA,
+	 * if it's within the range of regtable.
+	 */
+	cfa = dbg->dbg_frame_cfa_value;
+	if (cfa < DW_REG_TABLE_SIZE) {
+		reg_table->rules[cfa].dw_offset_relevant =
+		    CFA.dw_offset_relevant;
+		reg_table->rules[cfa].dw_regnum = CFA.dw_regnum;
+		reg_table->rules[cfa].dw_offset = CFA.dw_offset_or_block_len;
+	}
+
+	/*
+	 * Copy other columns.
+	 */
+	for (i = 0; i < DW_REG_TABLE_SIZE && i < dbg->dbg_frame_rule_table_size;
+	     i++) {
+
+		/* Do not overwrite CFA column */
+		if (i == cfa)
+			continue;
+
+		reg_table->rules[i].dw_offset_relevant =
+		    rt->rt3_rules[i].dw_offset_relevant;
+		reg_table->rules[i].dw_regnum = rt->rt3_rules[i].dw_regnum;
+		reg_table->rules[i].dw_offset =
+		    rt->rt3_rules[i].dw_offset_or_block_len;
+	}
+
+	*row_pc = pc;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_fde_info_for_reg3(Dwarf_Fde fde, Dwarf_Half table_column,
+    Dwarf_Addr pc_requested, Dwarf_Small *value_type,
+    Dwarf_Signed *offset_relevant, Dwarf_Signed *register_num,
+    Dwarf_Signed *offset_or_block_len, Dwarf_Ptr *block_ptr,
+    Dwarf_Addr *row_pc, Dwarf_Error *error)
+{
+	Dwarf_Regtable3 *rt;
+	Dwarf_Debug dbg;
+	Dwarf_Addr pc;
+	int ret;
+
+	dbg = fde != NULL ? fde->fde_dbg : NULL;
+
+	if (fde == NULL || value_type == NULL || offset_relevant == NULL ||
+	    register_num == NULL || offset_or_block_len == NULL ||
+	    block_ptr == NULL || row_pc == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (pc_requested < fde->fde_initloc ||
+	    pc_requested >= fde->fde_initloc + fde->fde_adrange) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
+		return (DW_DLV_ERROR);
+	}
+
+	ret = _dwarf_frame_get_internal_table(fde, pc_requested, &rt, &pc,
+	    error);
+	if (ret != DW_DLE_NONE)
+		return (DW_DLV_ERROR);
+
+	if (table_column >= dbg->dbg_frame_rule_table_size) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_FRAME_TABLE_COL_BAD);
+		return (DW_DLV_ERROR);
+	}
+
+	*value_type = RL.dw_value_type;
+	*offset_relevant = RL.dw_offset_relevant;
+	*register_num = RL.dw_regnum;
+	*offset_or_block_len = RL.dw_offset_or_block_len;
+	*block_ptr = RL.dw_block_ptr;
+	*row_pc = pc;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_fde_info_for_cfa_reg3(Dwarf_Fde fde, Dwarf_Addr pc_requested,
+    Dwarf_Small *value_type, Dwarf_Signed *offset_relevant,
+    Dwarf_Signed *register_num, Dwarf_Signed *offset_or_block_len,
+    Dwarf_Ptr *block_ptr, Dwarf_Addr *row_pc, Dwarf_Error *error)
+{
+	Dwarf_Regtable3 *rt;
+	Dwarf_Debug dbg;
+	Dwarf_Addr pc;
+	int ret;
+
+	dbg = fde != NULL ? fde->fde_dbg : NULL;
+
+	if (fde == NULL || value_type == NULL || offset_relevant == NULL ||
+	    register_num == NULL || offset_or_block_len == NULL ||
+	    block_ptr == NULL || row_pc == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (pc_requested < fde->fde_initloc ||
+	    pc_requested >= fde->fde_initloc + fde->fde_adrange) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
+		return (DW_DLV_ERROR);
+	}
+
+	ret = _dwarf_frame_get_internal_table(fde, pc_requested, &rt, &pc,
+	    error);
+	if (ret != DW_DLE_NONE)
+		return (DW_DLV_ERROR);
+
+	*value_type = CFA.dw_value_type;
+	*offset_relevant = CFA.dw_offset_relevant;
+	*register_num = CFA.dw_regnum;
+	*offset_or_block_len = CFA.dw_offset_or_block_len;
+	*block_ptr = CFA.dw_block_ptr;
+	*row_pc = pc;
+
+	return (DW_DLV_OK);
+}
+
+#undef	RL
+#undef	CFA
+
+int
+dwarf_get_fde_info_for_all_regs3(Dwarf_Fde fde, Dwarf_Addr pc_requested,
+    Dwarf_Regtable3 *reg_table, Dwarf_Addr *row_pc, Dwarf_Error *error)
+{
+	Dwarf_Regtable3 *rt;
+	Dwarf_Debug dbg;
+	Dwarf_Addr pc;
+	int ret;
+
+	dbg = fde != NULL ? fde->fde_dbg : NULL;
+
+	if (fde == NULL || reg_table == NULL || reg_table->rt3_rules == NULL ||
+	    row_pc == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	assert(dbg != NULL);
+
+	if (pc_requested < fde->fde_initloc ||
+	    pc_requested >= fde->fde_initloc + fde->fde_adrange) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
+		return (DW_DLV_ERROR);
+	}
+
+	ret = _dwarf_frame_get_internal_table(fde, pc_requested, &rt, &pc,
+	    error);
+	if (ret != DW_DLE_NONE)
+		return (DW_DLV_ERROR);
+
+	ret = _dwarf_frame_regtable_copy(dbg, &reg_table, rt, error);
+	if (ret != DW_DLE_NONE)
+		return (DW_DLV_ERROR);
+
+	*row_pc = pc;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_expand_frame_instructions(Dwarf_Cie cie, Dwarf_Ptr instruction,
+    Dwarf_Unsigned len, Dwarf_Frame_Op **ret_oplist, Dwarf_Signed *ret_opcnt,
+    Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+	int ret;
+
+	dbg = cie != NULL ? cie->cie_dbg : NULL;
+
+	if (cie == NULL || instruction == NULL || len == 0 ||
+	    ret_oplist == NULL || ret_opcnt == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	ret = _dwarf_frame_get_fop(dbg, cie->cie_addrsize, instruction, len,
+	    ret_oplist, ret_opcnt, error);
+	if (ret != DW_DLE_NONE)
+		return (DW_DLV_ERROR);
+
+	return (DW_DLV_OK);
+}
+
+Dwarf_Half
+dwarf_set_frame_rule_table_size(Dwarf_Debug dbg, Dwarf_Half value)
+{
+	Dwarf_Half old_value;
+
+	old_value = dbg->dbg_frame_rule_table_size;
+	dbg->dbg_frame_rule_table_size = value;
+
+	return (old_value);
+}
+
+Dwarf_Half
+dwarf_set_frame_rule_initial_value(Dwarf_Debug dbg, Dwarf_Half value)
+{
+	Dwarf_Half old_value;
+
+	old_value = dbg->dbg_frame_rule_initial_value;
+	dbg->dbg_frame_rule_initial_value = value;
+
+	return (old_value);
+}
+
+Dwarf_Half
+dwarf_set_frame_cfa_value(Dwarf_Debug dbg, Dwarf_Half value)
+{
+	Dwarf_Half old_value;
+
+	old_value = dbg->dbg_frame_cfa_value;
+	dbg->dbg_frame_cfa_value = value;
+
+	return (old_value);
+}
+
+Dwarf_Half
+dwarf_set_frame_same_value(Dwarf_Debug dbg, Dwarf_Half value)
+{
+	Dwarf_Half old_value;
+
+	old_value = dbg->dbg_frame_same_value;
+	dbg->dbg_frame_same_value = value;
+
+	return (old_value);
+}
+
+Dwarf_Half
+dwarf_set_frame_undefined_value(Dwarf_Debug dbg, Dwarf_Half value)
+{
+	Dwarf_Half old_value;
+
+	old_value = dbg->dbg_frame_undefined_value;
+	dbg->dbg_frame_undefined_value = value;
+
+	return (old_value);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_funcs.m4	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_funcs.m4 2073 2011-10-27 03:30:47Z jkoshy $");
+
+/* WARNING: GENERATED FROM __file__. */
+
+divert(-1)
+include(SRCDIR`/dwarf_nametbl.m4')
+divert(0)
+MAKE_NAMETBL_API(func,Func,func,static_func)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_AT_name.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,259 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_AT_name.3 3142 2015-01-29 23:11:14Z jkoshy $
+.\"
+.Dd April 22, 2011
+.Os
+.Dt DWARF_GET_AT_NAME 3
+.Sh NAME
+.Nm dwarf_get_ACCESS_name ,
+.Nm dwarf_get_AT_name ,
+.Nm dwarf_get_ATE_name ,
+.Nm dwarf_get_CC_name ,
+.Nm dwarf_get_CFA_name ,
+.Nm dwarf_get_CHILDREN_name ,
+.Nm dwarf_get_DS_name ,
+.Nm dwarf_get_DSC_name ,
+.Nm dwarf_get_EH_name ,
+.Nm dwarf_get_END_name ,
+.Nm dwarf_get_FORM_name ,
+.Nm dwarf_get_ID_name ,
+.Nm dwarf_get_INL_name ,
+.Nm dwarf_get_LANG_name ,
+.Nm dwarf_get_LNE_name ,
+.Nm dwarf_get_LNS_name ,
+.Nm dwarf_get_MACINFO_name ,
+.Nm dwarf_get_OP_name ,
+.Nm dwarf_get_ORD_name ,
+.Nm dwarf_get_TAG_name ,
+.Nm dwarf_get_VIRTUALITY_name ,
+.Nm dwarf_get_VIS_name
+.Nd retrieve the symbolic names of DWARF constants
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_ACCESS_name
+.Fa "unsigned val"
+.Fa "char **str"
+.Fc
+.Ft int
+.Fo dwarf_get_AT_name
+.Fa "unsigned val"
+.Fa "char **str"
+.Fc
+.Ft int
+.Fo dwarf_get_ATE_name
+.Fa "unsigned val"
+.Fa "char **str"
+.Fc
+.Ft int
+.Fo dwarf_get_CC_name
+.Fa "unsigned val"
+.Fa "char **str"
+.Fc
+.Ft int
+.Fo dwarf_get_CFA_name
+.Fa "unsigned val"
+.Fa "char **str"
+.Fc
+.Ft int
+.Fo dwarf_get_CHILDREN_name
+.Fa "unsigned val"
+.Fa "char **str"
+.Fc
+.Ft int
+.Fo dwarf_get_DS_name
+.Fa "unsigned val"
+.Fa "char **str"
+.Fc
+.Ft int
+.Fo dwarf_get_DSC_name
+.Fa "unsigned val"
+.Fa "char **str"
+.Fc
+.Ft int
+.Fo dwarf_get_EH_name
+.Fa "unsigned val"
+.Fa "char **str"
+.Fc
+.Ft int
+.Fo dwarf_get_END_name
+.Fa "unsigned val"
+.Fa "char **str"
+.Fc
+.Ft int
+.Fo dwarf_get_FORM_name
+.Fa "unsigned val"
+.Fa "char **str"
+.Fc
+.Ft int
+.Fo dwarf_get_ID_name
+.Fa "unsigned val"
+.Fa "char **str"
+.Fc
+.Ft int
+.Fo dwarf_get_INL_name
+.Fa "unsigned val"
+.Fa "char **str"
+.Fc
+.Ft int
+.Fo dwarf_get_LANG_name
+.Fa "unsigned val"
+.Fa "char **str"
+.Fc
+.Ft int
+.Fo dwarf_get_LNE_name
+.Fa "unsigned val"
+.Fa "char **str"
+.Fc
+.Ft int
+.Fo dwarf_get_LNS_name
+.Fa "unsigned val"
+.Fa "char **str"
+.Fc
+.Ft int
+.Fo dwarf_get_MACINFO_name
+.Fa "unsigned val"
+.Fa "char **str"
+.Fc
+.Ft int
+.Fo dwarf_get_OP_name
+.Fa "unsigned val"
+.Fa "char **str"
+.Fc
+.Ft int
+.Fo dwarf_get_ORD_name
+.Fa "unsigned val"
+.Fa "char **str"
+.Fc
+.Ft int
+.Fo dwarf_get_TAG_name
+.Fa "unsigned val"
+.Fa "char **str"
+.Fc
+.Ft int
+.Fo dwarf_get_VIRTUALITY_name
+.Fa "unsigned val"
+.Fa "char **str"
+.Fc
+.Ft int
+.Fo dwarf_get_VIS_name
+.Fa "unsigned val"
+.Fa "char **str"
+.Fc
+.Sh DESCRIPTION
+These functions return the symbolic name of a numeric DWARF constant.
+.Pp
+Argument
+.Ar val
+specifies the numeric value whose symbolic name is desired.
+.Pp
+Argument
+.Ar str
+should point to a location which will hold the returned
+NUL-terminated string containing the symbolic name of the
+specified value.
+.Pp
+The list of functions and the DWARF constants that they accept are:
+.Pp
+.Bl -tag -width ".Fn dwarf_get_VIRTUALITY_name" -compact
+.It Fn dwarf_get_ACCESS_name
+.Dv DW_ACCESS_*
+constants.
+.It Fn dwarf_get_AT_name
+.Dv DW_AT_*
+constants.
+.It Fn dwarf_get_ATE_name
+.Dv DW_ATE_*
+constants.
+.It Fn dwarf_get_CC_name
+.Dv DW_CC_*
+constants.
+.It Fn dwarf_get_CFA_name
+.Dv DW_CFA_*
+constants.
+.It Fn dwarf_get_CHILDREN_name
+.Dv DW_CHILDREN_*
+constants.
+.It Fn dwarf_get_DS_name
+.Dv DW_DS_*
+constants.
+.It Fn dwarf_get_DSC_name
+.Dv DW_DSC_*
+constants.
+.It Fn dwarf_get_EH_name
+.Dv DW_EH_PE_*
+constants.
+.It Fn dwarf_get_END_name
+.Dv DW_END_*
+constants.
+.It Fn dwarf_get_FORM_name
+.Dv DW_FORM_*
+constants.
+.It Fn dwarf_get_ID_name
+.Dv DW_ID_*
+constants.
+.It Fn dwarf_get_INL_name
+.Dv DW_INL_*
+constants.
+.It Fn dwarf_get_LANG_name
+.Dv DW_LANG_*
+constants.
+.It Fn dwarf_get_LNE_name
+.Dv DW_LNE_*
+constants.
+.It Fn dwarf_get_LNS_name
+.Dv DW_LNS_*
+constants.
+.It Fn dwarf_get_MACINFO_name
+.Dv DW_MACINFO_*
+constants.
+.It Fn dwarf_get_OP_name
+.Dv DW_OP_*
+constants.
+.It Fn dwarf_get_ORD_name
+.Dv DW_ORD_*
+constants.
+.It Fn dwarf_get_TAG_name
+.Dv DW_TAG_*
+constants.
+.It Fn dwarf_get_VIRTUALITY_name
+.Dv DW_VIRTUALITY_*
+constants.
+.It Fn dwarf_get_VIS_name
+.Dv DW_VIS_*
+constants.
+.El
+.Sh RETURN VALUES
+These functions return
+.Dv DW_DLV_OK on success.
+If the DWARF constant denoted by argument
+.Ar val
+is not recognized, these function return
+.Dv DW_DLV_NO_ENTRY .
+.Sh SEE ALSO
+.Xr dwarf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_abbrev.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,179 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_abbrev.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd March 27, 2011
+.Os
+.Dt DWARF_GET_ABBREV 3
+.Sh NAME
+.Nm dwarf_get_abbrev
+.Nd retrieve abbreviation information
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_abbrev
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Unsigned offset"
+.Fa "Dwarf_Abbrev *ret_abbrev"
+.Fa "Dwarf_Unsigned *length"
+.Fa "Dwarf_Unsigned *attr_count"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_abbrev
+retrieves information about an abbreviation from the DWARF abbreviations
+section,
+.Dq ".debug_abbrev" .
+Abbreviation information is returned using an opaque descriptor
+of type
+.Vt Dwarf_Abbrev .
+The returned
+.Vt Dwarf_Abbrev
+descriptor may then be passed to the other abbreviation related APIs
+in the DWARF(3) API to retrieve specific information about the
+abbreviation.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF debug context allocated using
+.Xr dwarf_init 3 .
+.Pp
+Argument
+.Ar offset
+should be an offset, relative to the
+.Dq ".debug_abbrev"
+section, to the start of an abbreviation entry.
+.Pp
+Argument
+.Ar ret_abbrev
+should point to a location that will hold a pointer to the
+returned
+.Vt Dwarf_Abbrev
+descriptor.
+.Pp
+Argument
+.Ar length
+should point to a location that will hold the number of bytes used
+by the abbrevation in the DWARF
+.Dq ".debug_abbrev"
+section.
+.Pp
+Argument
+.Ar attr_count
+should point to a location that will hold the number of
+attributes in the abbrevation.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Ss Memory Management
+The memory area used for the
+.Vt Dwarf_Abbrev
+descriptor returned in argument
+.Ar ret_abbrev
+is allocated by the
+.Lb libdwarf .
+Application code should use function
+.Fn dwarf_dealloc
+with the allocation type
+.Dv DW_DLA_ABBREV
+to free the memory area when the
+.Vt Dwarf_Abbrev
+descriptor is no longer needed.
+.Ss Application Programming Notes
+The last abbreviation entry in a standard DWARF abbreviation section
+will have a special length value of 1.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_get_abbrev
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+It returns
+.Dv DW_DLV_NO_ENTRY
+if there is no abbreviation information at offset
+.Ar offset .
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_abbrev
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_NO_ENTRY"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar dbg ,
+.Ar ret_abbrev ,
+.Ar length
+or
+.Ar attr_count
+was NULL.
+.It Bq Er DW_DLE_NO_ENTRY
+There is no abbreviation information at offset
+.Ar offset .
+.El
+.Sh EXAMPLE
+To loop through all the abbreviation information associated with
+a DWARF debug context, use:
+.Bd -literal -offset indent
+Dwarf_Debug dbg;
+Dwarf_Abbrev ab;
+Dwarf_Off aboff;
+Dwarf_Unsigned length, attr_count;
+Dwarf_Half tag;
+Dwarf_Error de;
+int ret;
+
+while ((ret = dwarf_next_cu_header(dbg, NULL, NULL, &aboff,
+    NULL, NULL, &de)) ==  DW_DLV_OK) {
+	while ((ret = dwarf_get_abbrev(re->dbg, aboff, &ab, &length,
+	    &attr_count, &de)) == DW_DLV_OK) {
+		if (length == 1)	/* Last entry. */
+			break;
+		aboff += length;
+		if (dwarf_get_abbrev_tag(ab, &tag, &de) != DW_DLV_OK) {
+			warnx("dwarf_get_abbrev_tag failed: %s",
+			    dwarf_errmsg(de));
+			continue;
+		}
+	if (ret != DW_DLV_OK)
+		warnx("dwarf_get_abbrev: %s", dwarf_errmsg(de));
+}
+if (ret == DW_DLV_ERROR)
+	warnx("dwarf_next_cu_header: %s", dwarf_errmsg(de));
+.Ed
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_dealloc 3 ,
+.Xr dwarf_get_abbrev_tag 3 ,
+.Xr dwarf_get_abbrev_code 3 ,
+.Xr dwarf_get_abbrev_children_flag 3 ,
+.Xr dwarf_get_abbrev_entry 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_abbrev_children_flag.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,100 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_abbrev_children_flag.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd March 14, 2011
+.Os
+.Dt DWARF_GET_ABBREV_CHILDREN_FLAG 3
+.Sh NAME
+.Nm dwarf_get_abbrev_children_flag
+.Nd return a flag indicating the presence of children
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_abbrev_children_flag
+.Fa "Dwarf_Abbrev abbrev"
+.Fa "Dwarf_Signed *ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_abbrev_children_flag
+retrieves a flag indicating whether the DWARF debug information entry
+associated with a DWARF abbreviation descriptor has child entries.
+.Pp
+Argument
+.Ar abbrev
+should be a valid DWARF abbreviation descriptor, as returned by
+.Xr dwarf_get_abbrev 3 .
+.Pp
+Argument
+.Ar ret
+should point to a location which will hold the returned
+flag.
+The value returned will be one of the following:
+.Bl -tag -width ".Dv DW_CHILDREN_yes" -compact
+.It Dv DW_CHILDREN_yes
+The debugging information entry associated with the
+specified abbreviation descriptor has children.
+.It Dv DW_CHILDREN_no
+The debugging information entry associated with the
+specified abbreviation descriptor has no children.
+.El
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Pp
+.Sh RETURN VALUES
+Function
+.Fn dwarf_get_abbrev_children_flag
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_abbrev_children_flag
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Either of arguments
+.Ar abbrev
+or
+.Ar ret
+was NULL.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_abbrev 3 ,
+.Xr dwarf_get_abbrev_code 3 ,
+.Xr dwarf_get_abbrev_tag 3 ,
+.Xr dwarf_get_abbrev_entry 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_abbrev_code.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,86 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_abbrev_code.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd March 13, 2011
+.Os
+.Dt DWARF_GET_ABBREV_CODE 3
+.Sh NAME
+.Nm dwarf_get_abbrev_code
+.Nd retrieve the abbreviation code for an abbreviation
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_abbrev_code
+.Fa "Dwarf_Abbrev abbrev"
+.Fa "Dwarf_Unsigned *ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_abbrev_code
+retrieves the abbreviation code for the abbreviation entry descriptor
+referenced by argument
+.Ar abbrev .
+.Pp
+Argument
+.Ar ret
+should point to a location which will hold the returned
+abbreviation code.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_get_abbrev_code
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_abbrev_code
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Either of arguments
+.Ar abbrev
+or
+.Ar ret
+was NULL.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_abbrev 3 ,
+.Xr dwarf_get_abbrev_tag 3 ,
+.Xr dwarf_get_abbrev_children_flag 3 ,
+.Xr dwarf_get_abbrev_entry 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_abbrev_entry.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,159 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_abbrev_entry.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd April 02, 2011
+.Os
+.Dt DWARF_GET_ABBREV_ENTRY 3
+.Sh NAME
+.Nm dwarf_get_abbrev_entry
+.Nd retrieve attribute information from an abbreviation descriptor
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_abbrev_entry
+.Fa "Dwarf_Abbrev abbrev"
+.Fa "Dwarf_Signed ndx"
+.Fa "Dwarf_Half *code"
+.Fa "Dwarf_Signed *form"
+.Fa "Dwarf_Off *offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_abbrev_entry
+retrieves attribute information from a DWARF abbreviation descriptor.
+.Pp
+Argument
+.Ar abbrev
+should be a valid abbreviation descriptor, as returned by function
+.Xr dwarf_get_abbrev 3 .
+.Pp
+Argument
+.Ar ndx
+specifies the 0-based index of the attribute.
+The total count of the attributes contained in the abbreviation
+entry can be retrieved using the function
+.Xr dwarf_get_abbrev 3 .
+.Pp
+Argument
+.Ar code
+should point to a location which will hold a returned
+attribute code.
+.Pp
+Argument
+.Ar form
+should point to a location which will hold the returned
+form of the attribute.
+.Pp
+Argument
+.Ar offset
+should point to a location which will hold a returned offset, relative
+to the
+.Dq ".debug_abbrev"
+section, for the specified attribute.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to return an error descriptor in case
+of an error.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_get_abbrev_entry
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+It returns
+.Dv DW_DLV_NO_ENTRY
+if the attribute index specified by argument
+.Ar ndx
+is out of range.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_abbrev_entry
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_NO_ENTRY"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar abbrev ,
+.Ar code ,
+.Ar form
+or
+.Ar offset
+was NULL.
+.It Bq Er DW_DLE_NO_ENTRY
+The attribute index specified by argument
+.Ar ndx
+was out of range.
+.El
+.Sh EXAMPLE
+To loop through all the attribute entries contained in the
+abbreviation section, use:
+.Bd -literal -offset indent
+Dwarf_Debug dbg;
+Dwarf_Abbrev ab;
+Dwarf_Off aboff, atoff;
+Dwarf_Signed form;
+Dwarf_Half attr;
+Dwarf_Unsigned length, attr_count;
+Dwarf_Error de;
+int i, ret;
+
+/* ...allocate 'dbg' using dwarf_init(3) ... */
+
+while ((ret = dwarf_next_cu_header(dbg, NULL, NULL, &aboff,
+    NULL, NULL, &de)) ==  DW_DLV_OK) {
+	while ((ret = dwarf_get_abbrev(dbg, aboff, &ab, &length,
+	    &attr_count, &de)) == DW_DLV_OK) {
+		if (length == 1)	/* Last entry. */
+			break;
+		aboff += length;
+		for (i = 0; (Dwarf_Unsigned) i < attr_count; i++) {
+			if (dwarf_get_abbrev_entry(ab, i,
+			    &attr, &form, &atoff, &de) != DW_DLV_OK) {
+				warnx("dwarf_get_abbrev_entry failed:"
+				    " %s", dwarf_errmsg(de));
+				continue;
+			}
+			/* .. use the retrieved information ... */
+		}
+	}
+
+	if (ret != DW_DLV_OK)
+		warnx("dwarf_get_abbrev: %s", dwarf_errmsg(de));
+}
+
+if (ret == DW_DLV_ERROR)
+	warnx("dwarf_next_cu_header: %s", dwarf_errmsg(de));
+.Ed
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_abbrev 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_abbrev_tag.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,86 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_abbrev_tag.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd March 13, 2011
+.Os
+.Dt DWARF_GET_ABBREV_TAG 3
+.Sh NAME
+.Nm dwarf_get_abbrev_tag
+.Nd retrieve the tag for an abbreviation
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_abbrev_tag
+.Fa "Dwarf_Abbrev abbrev"
+.Fa "Dwarf_Half *ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_abbrev_tag
+retrieves the tag for the abbreviation entry descriptor referenced by
+argument
+.Ar abbrev .
+.Pp
+Argument
+.Ar ret
+should point to a location which will hold the returned
+abbreviation tag.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_get_abbrev_tag
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_abbrev_tag
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Either of arguments
+.Ar abbrev
+or
+.Ar ret
+was NULL.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_abbrev 3 ,
+.Xr dwarf_get_abbrev_code 3 ,
+.Xr dwarf_get_abbrev_children_flag 3 ,
+.Xr dwarf_get_abbrev_entry 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_address_size.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,82 @@
+.\" Copyright (c) 2010 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_address_size.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd April 14, 2010
+.Os
+.Dt DWARF_GET_ADDRESS_SIZE 3
+.Sh NAME
+.Nm dwarf_get_address_size
+.Nd return the number of bytes needed to represent an address
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_address_size
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Half *addr_size"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_address_size
+returns the size in bytes of a native address for a program object.
+.Pp
+Argument
+.Ar dbg
+should denote a DWARF debug context created from a program object using
+.Xr dwarf_init 3 .
+Argument
+.Ar addr_size
+should point to a location that will hold the returned size.
+Argument
+.Ar err ,
+if non-NULL, it will be used to return error information.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_tag
+returns
+.Dv DW_DLV_OK .
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_address_size
+can fail with the following error:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Either of arguments
+.Ar dbg
+or
+.Ar addr_size
+was NULL.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_init 3 ,
+.Xr dwarf_finish 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_arange.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,121 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_arange.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd April 16, 2011
+.Os
+.Dt DWARF_GET_ARANGE 3
+.Sh NAME
+.Nm dwarf_get_arange
+.Nd retrieve the address range descriptor for an address
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_arange
+.Fa "Dwarf_Arange *ar_list"
+.Fa "Dwarf_Unsigned ar_cnt"
+.Fa "Dwarf_Addr addr"
+.Fa "Dwarf_Arange *ret_ar"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_arange
+searches an array of
+.Vt Dwarf_Arange
+descriptors for one that covers a given address.
+.Pp
+Argument
+.Ar ar_list
+should point to an array of
+.Vt Dwarf_Arange
+descriptors.
+.Pp
+Argument
+.Ar ar_cnt
+specifies the number of
+.Vt Dwarf_Arange
+descriptors in the array pointed to by argument
+.Ar ar_list .
+.Pp
+Argument
+.Ar addr
+specifies the address being looked up.
+.Pp
+Argument
+.Ar ret_ar
+will be used to store the
+.Vt Dwarf_Arange
+descriptor that covers the given address.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_get_arange
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+It returns
+.Dv DW_DLV_NO_ENTRY
+if there is no
+.Vt Dwarf_Arange
+descriptor that covers the provided address.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_arange
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_NO_ENTRY"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar dbg ,
+.Ar ar_list
+or
+.Ar ret_ar
+was NULL.
+.It Bq Er DW_DLE_ARGUMENT
+Value of argument
+.Ar ar_cnt
+equals to 0.
+.It Bq Er DW_DLE_NO_ENTRY
+A
+.Vt Dwarf_Arange
+descriptor that covers the given address
+was not found.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_aranges 3 ,
+.Xr dwarf_get_arange_cu_header_offset 3 ,
+.Xr dwarf_get_arange_info 3 ,
+.Xr dwarf_get_cu_die_offset 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_arange_info.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,135 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_arange_info.3 3142 2015-01-29 23:11:14Z jkoshy $
+.\"
+.Dd April 16, 2011
+.Os
+.Dt DWARF_GET_ARANGE_INFO 3
+.Sh NAME
+.Nm dwarf_get_arange_info
+.Nd extract address range information from a descriptor
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_arange_info
+.Fa "Dwarf_Arange ar"
+.Fa "Dwarf_Addr *start"
+.Fa "Dwarf_Unsigned *length"
+.Fa "Dwarf_Off *cu_die_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_arange_info
+extracts address range information from a
+.Vt Dwarf_Arange
+descriptor.
+.Pp
+Argument
+.Ar ar
+should reference a valid
+.Vt Dwarf_Arange
+descriptor returned by function
+.Xr dwarf_get_aranges 3 .
+.Pp
+Argument
+.Ar start
+should point to a location which will hold the start value of the
+address range associated with the descriptor.
+.Pp
+Argument
+.Ar length
+should point to a location which will hold the length in bytes of the
+address range associated with the descriptor.
+.Pp
+Argument
+.Ar cu_die_offset
+should point to a location which will be set to an offset, relative to
+the
+.Dq ".debug_info"
+section, of the first debugging information entry in the compilation
+unit associated with argument
+.Ar ar .
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_get_arange_info
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_arange_info
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar ar ,
+.Ar start ,
+.Ar length
+or
+.Ar cu_die_offset
+was NULL.
+.El
+.Sh EXAMPLE
+To loop through all the address lookup table entries, use:
+.Bd -literal -offset indent
+Dwarf_Debug dbg;
+Dwarf_Addr start;
+Dwarf_Arange *aranges;
+Dwarf_Off die_off;
+Dwarf_Signed i, cnt;
+Dwarf_Unsigned length;
+Dwarf_Error de;
+
+if (dwarf_get_aranges(dbg, &aranges, &cnt, &de) != DW_DLV_OK)
+	errx(EXIT_FAILURE, "dwarf_get_aranges: %s",
+	    dwarf_errmsg(de));
+for (i = 0; i < cnt; i++) {
+	if (dwarf_get_arange_info(aranges[i], &start, &length,
+	    &die_off, &de) != DW_DLV_OK) {
+		warnx("dwarf_get_arange_info: %s",
+		    dwarf_errmsg(de));
+		continue;
+	}
+	/* Do something with the returned information. */
+}
+.Ed
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_arange 3 ,
+.Xr dwarf_get_aranges 3 ,
+.Xr dwarf_get_arange_cu_header_offset 3 ,
+.Xr dwarf_get_cu_die_offset 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_aranges.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,148 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_aranges.3 2122 2011-11-09 15:35:14Z jkoshy $
+.\"
+.Dd November 9, 2011
+.Os
+.Dt DWARF_GET_ARANGES 3
+.Sh NAME
+.Nm dwarf_get_aranges
+.Nd retrieve program address space mappings
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_aranges
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Arange **ar_list"
+.Fa "Dwarf_Signed *ar_cnt"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+The function
+.Fn dwarf_get_aranges
+retrieves address range information from the
+.Dq ".debug_aranges"
+DWARF section.
+Information about address ranges is returned using opaque descriptors
+of type
+.Vt Dwarf_Arange ,
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF debug context allocated using
+.Xr dwarf_init 3 .
+.Pp
+Argument
+.Ar ar_list
+should point to a location which will be set to a pointer to an array
+of
+.Vt Dwarf_Arange
+descriptors.
+.Pp
+Argument
+.Ar ar_cnt
+should point to a location which will be set to the number of
+descriptors returned.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Ss Memory Management
+The memory area used for the array returned in argument
+.Ar ar_list
+is owned by
+.Lb libdwarf .
+Application code should not attempt to directly free this area.
+Portable applications should instead use
+.Xr dwarf_dealloc 3
+to indicate that the memory area may be freed.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_get_aranges
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+It returns
+.Dv DW_DLV_NO_ENTRY
+if there is no
+.Dq ".debug_aranges"
+section associated with the specified debugging context.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_aranges
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_NO_ENTRY"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar dbg ,
+.Ar ar_list
+or
+.Ar ar_cnt
+was NULL.
+.It Bq Er DW_DLE_NO_ENTRY
+The debugging context
+.Ar dbg
+did not contain a
+.Dq ".debug_aranges"
+string section.
+.El
+.Sh EXAMPLE
+To loop through all the address lookup table entries, use:
+.Bd -literal -offset indent
+Dwarf_Debug dbg;
+Dwarf_Addr start;
+Dwarf_Arange *aranges;
+Dwarf_Off die_off;
+Dwarf_Signed i, cnt;
+Dwarf_Unsigned length;
+Dwarf_Error de;
+
+if (dwarf_get_aranges(dbg, &aranges, &cnt, &de) != DW_DLV_OK)
+	errx(EXIT_FAILURE, "dwarf_get_aranges: %s",
+	    dwarf_errmsg(de));
+
+for (i = 0; i < cnt; i++) {
+	if (dwarf_get_arange_info(aranges[i], &start, &length,
+	    &die_off, &de) != DW_DLV_OK) {
+		warnx("dwarf_get_arange_info: %s",
+		    dwarf_errmsg(de));
+		continue;
+	}
+	/* Do something with the returned information. */
+}
+.Ed
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_arange 3 ,
+.Xr dwarf_get_arange_cu_header_offset 3 ,
+.Xr dwarf_get_arange_info 3 ,
+.Xr dwarf_get_cu_die_offset 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_cie_index.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,86 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_cie_index.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd May 22, 2011
+.Os
+.Dt DWARF_GET_CIE_INDEX 3
+.Sh NAME
+.Nm dwarf_get_cie_index
+.Nd retrieve the index of a CIE descriptor
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_cie_index
+.Fa "Dwarf_Cie cie"
+.Fa "Dwarf_Signed *cie_index"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_cie_index
+retrieves the zero-based index of a given CIE descriptor in the array
+of CIE descriptors returned by the functions
+.Xr dwarf_get_fde_list 3
+and
+.Xr dwarf_get_fde_list_eh 3 .
+.Pp
+Argument
+.Ar cie
+should reference a valid DWARF CIE descriptor.
+.Pp
+Argument
+.Ar cie_index
+should point to a location that will hold the returned index.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_get_cie_index
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_cie_index
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Either of arugments
+.Ar cie
+or
+.Ar cie_index
+was NULL.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_cie_info 3 ,
+.Xr dwarf_get_cie_of_fde 3 ,
+.Xr dwarf_get_fde_list 3 ,
+.Xr dwarf_get_fde_list_eh 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_cie_info.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,150 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_cie_info.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd May 29, 2011
+.Os
+.Dt DWARF_GET_CIE_INFO 3
+.Sh NAME
+.Nm dwarf_get_cie_info
+.Nd retrieve information associated with a CIE descriptor
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_cie_info
+.Fa "Dwarf_Cie cie"
+.Fa "Dwarf_Unsigned *cie_byte_len"
+.Fa "Dwarf_Small *version"
+.Fa "char **augmentation"
+.Fa "Dwarf_Unsigned *caf"
+.Fa "Dwarf_Unsigned *daf"
+.Fa "Dwarf_Half *ra"
+.Fa "Dwarf_Ptr *init_inst"
+.Fa "Dwarf_Unsigned *inst_len"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_cie_info
+retrieves the information associated with a given CIE descriptor.
+.Pp
+Argument
+.Ar cie
+should reference a valid DWARF CIE descriptor, such as would be
+returned by function
+.Xr dwarf_get_cie_of_fde 3 .
+.Pp
+Argument
+.Ar cie_byte_len
+should point to a location that will hold the length in bytes of
+the CIE descriptor itself.
+.Pp
+Argument
+.Ar version
+should point to a location that will hold the version number of
+the CIE descriptor.
+.Pp
+Arugment
+.Ar augmentation
+should point to a location that will be set to a pointer to a
+NUL-terminated string containing augmentation data encoded as UTF-8.
+.Pp
+Argument
+.Ar caf
+should point to a location that will hold the code alignment
+factor recorded in the CIE descriptor.
+.Pp
+Arugment
+.Ar daf
+should point to a location that will hold the data alignment
+factor recorded in the CIE descriptor.
+.Pp
+Argument
+.Ar ra
+should point to a location that will hold the return address
+recorded in the CIE descriptor.
+.Pp
+Argument
+.Ar init_inst
+should point to a location that will be set to a pointer to an array
+of bytes containing the initial instructions associated with the CIE
+descriptor.
+.Pp
+Argument
+.Ar inst_len
+should point to a location that will hold the length in bytes
+of the initial instructions returned in argument
+.Ar init_inst .
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_get_cie_info
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_cie_info
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar cie ,
+.Ar cie_byte_len ,
+.Ar version ,
+.Ar augmentation ,
+.Ar caf ,
+.Ar daf ,
+.Ar ra ,
+.Ar init_inst
+or
+.Ar inst_len
+was NULL.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_cie_index 3 ,
+.Xr dwarf_get_cie_of_fde 3 ,
+.Xr dwarf_get_fde_at_pc 3 ,
+.Xr dwarf_get_fde_info_for_all_regs 3 ,
+.Xr dwarf_get_fde_info_for_all_regs3 3 ,
+.Xr dwarf_get_fde_info_for_cfa_reg3 3 ,
+.Xr dwarf_get_fde_info_for_reg 3 ,
+.Xr dwarf_get_fde_info_for_reg3 3 ,
+.Xr dwarf_get_fde_instr_bytes 3 ,
+.Xr dwarf_get_fde_list 3 ,
+.Xr dwarf_get_fde_list_eh 3 ,
+.Xr dwarf_get_fde_n 3 ,
+.Xr dwarf_get_fde_range 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_cie_of_fde.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,88 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_cie_of_fde.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd May 22, 2011
+.Os
+.Dt DWARF_GET_CIE_OF_FDE 3
+.Sh NAME
+.Nm dwarf_get_cie_of_fde
+.Nd retrieve CIE descriptor
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_cie_of_fde
+.Fa "Dwarf_Fde fde"
+.Fa "Dwarf_Cie *ret_cie"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_cie_of_fde
+retrieves the CIE descriptor associated with a given FDE descriptor.
+.Pp
+Argument
+.Ar fde
+should reference a valid FDE descriptor.
+.Pp
+Argument
+.Ar ret_cie
+should point to a location that will hold the returned CIE
+descriptor.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_get_cie_of_fde
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_cie_of_fde
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Either of arugments
+.Ar fde
+or
+.Ar ret_cie
+was NULL.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_cie_info 3 ,
+.Xr dwarf_get_cie_index 3 ,
+.Xr dwarf_get_fde_at_pc 3 ,
+.Xr dwarf_get_fde_n 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_cu_die_offset.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,103 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_cu_die_offset.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd April 10, 2011
+.Os
+.Dt DWARF_GET_CU_DIE_OFFSET 3
+.Sh NAME
+.Nm dwarf_get_arange_cu_header_offset ,
+.Nm dwarf_get_cu_die_offset
+.Nd retrieve compilation unit offsets
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_arange_cu_header_offset
+.Fa "Dwarf_Arange ar"
+.Fa "Dwarf_Off *ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_get_cu_die_offset
+.Fa "Dwarf_Arange ar"
+.Fa "Dwarf_Off *ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+These functions retrieve the offsets, relative to the
+.Dq ".debug_info"
+DWARF section, of the debugging information entries describing the
+compilation unit associated with a
+.Vt Dwarf_Arange
+descriptor.
+.Pp
+Function
+.Fn dwarf_get_arange_cu_header_offset
+retrieves the offset of the compilation unit header associated with
+argument
+.Ar ar ,
+and stores it in the location pointed to by argument
+.Ar ret .
+.Pp
+Function
+.Fn dwarf_get_cu_die_offset
+retrieves the offset of the debugging information entry for the
+compilation unit associated with argument
+.Ar ar ,
+and stores it in the location pointed to by argument
+.Ar ret .
+.Pp
+If argument
+.Ar err
+is not NULL, these functions will use it to store error information,
+in case of an error.
+.Sh RETURN VALUES
+On success, these functions returns
+.Dv DW_DLV_OK .
+In case of an error, they return
+.Dv DW_DLV_ERROR
+and set the argument
+.Ar err .
+.Sh ERRORS
+These functions may fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Ar ar
+was not a valid
+.Vt Dwarf_Arange
+descriptor.
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Ar ret
+was NULL.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_arange 3 ,
+.Xr dwarf_get_arange_info 3 ,
+.Xr dwarf_get_aranges 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_die_infotypes_flag.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,73 @@
+.\" Copyright (c) 2014 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_die_infotypes_flag.3 3118 2014-12-20 20:30:06Z jkoshy $
+.\"
+.Dd December 20, 2014
+.Os
+.Dt DWARF_GET_DIE_INFOTYPES_FLAG 3
+.Sh NAME
+.Nm dwarf_get_die_infotypes_flag
+.Nd indicate the originating DWARF section for a DIE
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft Dwarf_Bool
+.Fo dwarf_get_die_infotypes_flag
+.Fa "Dwarf_Die die"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_die_infotypes_flag
+returns a flag indicating the originating DWARF section for the
+debugging information entry referenced by argument
+.Ar die .
+.Pp
+Argument
+.Ar die
+should reference a valid debugging information entry descriptor.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_get_die_infotypes_flag
+returns a non-zero value if argument
+.Ar die
+originates in the
+.Dq .debug_info
+section.
+.Pp
+It returns zero if argument
+.Ar die
+originates in the
+.Dq .debug_types
+section.
+.Sh ERRORS
+Function
+.Fn dwarf_get_die_infotypes_flag
+always succeeds.
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_next_cu_header_c 3 ,
+.Xr dwarf_offdie_b 3 ,
+.Xr dwarf_siblingof_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_elf.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,103 @@
+.\" Copyright (c) 2009 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: dwarf_get_elf.3 2122 2011-11-09 15:35:14Z jkoshy $
+.\"
+.Dd November 9, 2011
+.Os
+.Dt DWARF_GET_ELF 3
+.Sh NAME
+.Nm dwarf_get_elf
+.Nd retrieve the
+.Vt Elf
+descriptor associated with a
+.Vt Dwarf_Debug
+instance
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_elf
+.Fa "Dwarf_Debug dbg"
+.Fa "Elf **elf"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_elf
+returns the
+.Vt Elf
+descriptor associated with a
+.Vt Dwarf_Debug
+instance.
+.Pp
+Argument
+.Ar dbg
+should be a handle to a valid
+.Vt Dwarf_Debug
+instance returned by a prior call to
+.Xr dwarf_init 3
+or
+.Xr dwarf_elf_init 3 .
+.Pp
+Argument
+.Ar elf
+points a location into which a handle to an
+.Vt Elf
+descriptor will be written.
+.Pp
+Argument
+.Ar err
+is used to record error information in case of failure.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_get_elf
+returns
+.Dv DW_DLV_OK .
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets argument
+.Ar err .
+.Sh EXAMPLES
+To retrieve the
+.Vt Elf
+instance associated with a
+.Vt Dwarf_Debug
+instance use:
+.Bd -literal -offset indent
+Dwarf_Debug dbg;
+Dwarf_Error de;
+Elf *elf;
+
+\&... allocate dbg using dwarf_init() etc ...
+
+if (dwarf_get_elf(dbg, &elf, &de) != DW_DLV_OK)
+	errx(EXIT_FAILURE, "dwarf_get_elf: %s", dwarf_errmsg(de));
+.Ed
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_errmsg 3 ,
+.Xr dwarf_init 3 ,
+.Xr dwarf_finish 3 ,
+.Xr elf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_fde_at_pc.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,125 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_fde_at_pc.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd May 22, 2011
+.Os
+.Dt DWARF_GET_FDE_AT_PC 3
+.Sh NAME
+.Nm dwarf_get_fde_at_pc
+.Nd retrieve the FDE descriptor for an address
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_fde_at_pc
+.Fa "Dwarf_Fde *fdelist"
+.Fa "Dwarf_Addr pc"
+.Fa "Dwarf_Fde *ret_fde"
+.Fa "Dwarf_Addr *lopc"
+.Fa "Dwarf_Addr *hipc"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_fde_at_pc
+searches the provided array of DWARF FDE descriptors for a descriptor
+covering a given program counter address.
+.Pp
+Argument
+.Ar fdelist
+should point to an array of FDE descriptors, as returned by the functions
+.Xr dwarf_get_fde_list 3
+or
+.Xr dwarf_get_fde_list_eh 3 .
+.Pp
+Argument
+.Ar pc
+should contain the program counter address being looked up.
+.Pp
+Argument
+.Ar ret_fde
+should point to a location that will hold the returned FDE descriptor.
+.Pp
+Argument
+.Ar lopc
+should point to a location that will be set to the lowest address
+covered by the returned FDE descriptor.
+.Pp
+Argument
+.Ar hipc
+should point to a location that will be set to the highest address
+covered by the returned FDE descriptor.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_get_fde_at_pc
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+It returns
+.Dv DW_DLV_NO_ENTRY
+if a FDE descriptor that covers the address specified by argument
+.Ar pc
+is not found.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_fde_at_pc
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_NO_ENTRY"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Va fdelist ,
+.Va ret_fde ,
+.Va lopc ,
+or
+.Va hipc
+was NULL.
+.It Bq Er DW_DLE_NO_ENTRY
+These was no FDE descriptor covering the address specified by argument
+.Ar pc .
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_cie_of_fde 3 ,
+.Xr dwarf_get_fde_info_for_all_regs 3 ,
+.Xr dwarf_get_fde_info_for_all_regs3 3 ,
+.Xr dwarf_get_fde_info_for_cfa_reg3 3 ,
+.Xr dwarf_get_fde_info_for_reg 3 ,
+.Xr dwarf_get_fde_info_for_reg3 3 ,
+.Xr dwarf_get_fde_instr_bytes 3 ,
+.Xr dwarf_get_fde_list 3 ,
+.Xr dwarf_get_fde_list_eh 3 ,
+.Xr dwarf_get_fde_n 3 ,
+.Xr dwarf_get_fde_range 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_fde_info_for_all_regs.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,156 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_fde_info_for_all_regs.3 3182 2015-04-10 16:08:10Z emaste $
+.\"
+.Dd June 4, 2011
+.Os
+.Dt DWARF_GET_FDE_INFO_FOR_ALL_REGS 3
+.Sh NAME
+.Nm dwarf_get_fde_info_for_all_regs
+.Nd retrieve register rule row
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_fde_info_for_all_regs
+.Fa "Dwarf_Fde fde"
+.Fa "Dwarf_Addr pc"
+.Fa "Dwarf_Regtable *reg_table"
+.Fa "Dwarf_Addr *row_pc"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_fde_info_for_all_regs
+retrieves a row from the register rule table associated with the given
+FDE descriptor.
+.Pp
+Argument
+.Ar fde
+should reference a valid DWARF FDE descriptor.
+.Pp
+Argument
+.Ar pc
+should hold the program counter address to be used to locate the
+desired table row.
+.Pp
+Argument
+.Ar reg_table
+should point to a
+.Vt Dwarf_Regtable
+descriptor which will hold the returned table row of register rules.
+.Pp
+Argument
+.Ar row_pc
+should point to a location which will be set to the lowest program
+counter address associated with the table row.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Pp
+The
+.Vt Dwarf_Regtable
+descriptor is defined in the header file
+.In libdwarf.h :
+.Bd -literal -offset indent
+typedef struct {
+	struct {
+		Dwarf_Small	dw_offset_relevant;
+		Dwarf_Half	dw_regnum;
+		Dwarf_Addr	dw_offset;
+	} rules[DW_REG_TABLE_SIZE];
+} Dwarf_Regtable;
+.Ed
+.Pp
+For each of the register rules returned,
+the
+.Va dw_offset_relevant
+field is set to 1 if the register rule has a offset value.
+The
+.Va dw_regnum
+field is set to the register number associated with the regsiter rule.
+The
+.Va dw_offset
+field is set to the offset value associated with the register rule.
+.Pp
+The number of register columns returned is either the constant
+value
+.Dv DW_REG_TABLE_SIZE as defined
+in the header file
+.In libdwarf.h ,
+or the value set by function
+.Xr dwarf_set_frame_rule_table_size 3 ,
+whichever is smaller.
+.Ss COMPATIBILITY
+Function
+.Fn dwarf_get_fde_info_for_all_regs
+is deprecated since it only supports DWARF2 frame sections.
+Applications should instead use function
+.Xr dwarf_get_fde_info_for_all_regs3 3
+which supports both DWARF2 and DWARF3 frame sections.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_get_fde_info_for_all_regs
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_fde_info_for_all_regs
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_PC_NOT_IN_FDE_RANGE"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar fde ,
+.Ar reg_table
+or
+.Ar row_pc
+was NULL.
+.It Bq Er DW_DLE_PC_NOT_IN_FDE_RANGE
+The program counter value provided in argument
+.Ar pc
+did not fall in the range covered by argument
+.Ar fde .
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_fde_at_pc 3 ,
+.Xr dwarf_get_fde_info_for_all_regs3 3 ,
+.Xr dwarf_get_fde_info_for_cfa_reg3 3 ,
+.Xr dwarf_get_fde_info_for_reg 3 ,
+.Xr dwarf_get_fde_info_for_reg3 3 ,
+.Xr dwarf_get_fde_n 3 ,
+.Xr dwarf_set_frame_cfa_value 3 ,
+.Xr dwarf_set_frame_rule_table_size 3 ,
+.Xr dwarf_set_frame_rule_initial_value 3 ,
+.Xr dwarf_set_frame_same_value 3 ,
+.Xr dwarf_set_frame_undefined_value 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_fde_info_for_all_regs3.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,183 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_fde_info_for_all_regs3.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd June 26, 2011
+.Os
+.Dt DWARF_GET_FDE_INFO_FOR_ALL_REGS3 3
+.Sh NAME
+.Nm dwarf_get_fde_info_for_all_regs3
+.Nd retrieve register rule row
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_fde_info_for_all_regs3
+.Fa "Dwarf_Fde fde"
+.Fa "Dwarf_Addr pc"
+.Fa "Dwarf_Regtable3 *reg_table"
+.Fa "Dwarf_Addr *row_pc"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_fde_info_for_all_regs3
+retrieves a row from the register rule table associated with the given
+FDE descriptor.
+.Pp
+Argument
+.Ar fde
+should reference a valid DWARF FDE descriptor.
+.Pp
+Argument
+.Ar pc
+should hold the program counter address to be used to locate the
+desired table row.
+.Pp
+Argument
+.Ar reg_table
+should point to a
+.Vt Dwarf_Regtable3
+descriptor which will hold the returned table row of register rules.
+The
+.Vt Dwarf_Regtable3
+descriptor is defined in the header file
+.In libdwarf.h :
+.Bd -literal -offset indent
+typedef struct {
+	Dwarf_Small	dw_offset_relevant;
+	Dwarf_Small	dw_value_type;
+	Dwarf_Half	dw_regnum;
+	Dwarf_Unsigned	dw_offset_or_block_len;
+	Dwarf_Ptr	dw_block_ptr;
+} Dwarf_Regtable_Entry3;
+
+typedef struct {
+	Dwarf_Regtable_Entry3	rt3_cfa_rule;
+	Dwarf_Half		rt3_reg_table_size;
+	Dwarf_Regtable_Entry3	*rt3_rules;
+} Dwarf_Regtable3;
+.Ed
+.Pp
+The
+.Va rt3_reg_table_size
+field specifies the maximum number of register rule columns to be
+returned, and should be set by the application before calling the
+function.
+The
+.Va rt3_rules
+field should point to a memory arena allocated by the application with
+space for at least
+.Vt rt3_reg_table_size
+descriptors of type
+.Vt Dwarf_Regtable_Entry3 .
+.Pp
+On a successful execution of this function, the
+.Va rt3_cfa_rule
+field will be set to the CFA register rule associated with the table
+row, and the
+.Va rt3_rules
+array will hold the returned register rules contained in the table row.
+.Pp
+For each register rule descriptor returned,
+the
+.Va dw_offset_relevant
+field will be set to 1 if the register rule has a offset value,
+the
+.Va dw_value_type
+field will be set to the type code of the register rule and the
+.Va dw_regnum
+field will be set to the register number associated with the register rule.
+If the register rule is of type
+.Dv DW_EXPR_OFFSET
+or
+.Dv DW_EXPR_VAL_OFFSET ,
+the
+.Va dw_offset_or_block_len
+field will be set to the offset value associated with the register rule.
+If the type is
+.Dv DW_EXPR_EXPRESSION
+or
+.Dv DW_EXPR_VAL_EXPRESSION ,
+the
+.Va dw_offset_or_block_len
+field will be set to the length in bytes of the DWARF expression block
+associated with the register rule.
+The
+.Va dw_block_ptr
+field will be set to a pointer to the content of the DWARF expression block
+associated with the register rule.
+.Pp
+Argument
+.Ar row_pc
+should point to a location which will be set to the lowest program
+counter address associated with the table row.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_get_fde_info_for_all_regs3
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_fde_info_for_all_regs3
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_PC_NOT_IN_FDE_RANGE"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar fde ,
+.Ar reg_table
+or
+.Ar row_pc
+was NULL.
+.It Bq Er DW_DLE_PC_NOT_IN_FDE_RANGE
+The program counter value provided in argument
+.Ar pc
+did not fall in the range covered by argument
+.Ar fde .
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_fde_at_pc 3 ,
+.Xr dwarf_get_fde_info_for_all_regs 3 ,
+.Xr dwarf_get_fde_info_for_cfa_reg3 3 ,
+.Xr dwarf_get_fde_info_for_reg 3 ,
+.Xr dwarf_get_fde_info_for_reg3 3 ,
+.Xr dwarf_get_fde_n 3 ,
+.Xr dwarf_set_frame_cfa_value 3 ,
+.Xr dwarf_set_frame_rule_table_size 3 ,
+.Xr dwarf_set_frame_rule_initial_value 3 ,
+.Xr dwarf_set_frame_same_value 3 ,
+.Xr dwarf_set_frame_undefined_value 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_fde_info_for_cfa_reg3.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,171 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_fde_info_for_cfa_reg3.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd June 12, 2011
+.Os
+.Dt DWARF_GET_FDE_INFO_FOR_CFA_REGS3 3
+.Sh NAME
+.Nm dwarf_get_fde_info_for_cfa_regs3
+.Nd retrieve a CFA register rule
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_fde_info_for_cfa_regs3
+.Fa "Dwarf_Fde fde"
+.Fa "Dwarf_Addr pc"
+.Fa "Dwarf_Small *type"
+.Fa "Dwarf_Signed *offset_relevant"
+.Fa "Dwarf_Signed *register_num"
+.Fa "Dwarf_Signed *offset_or_block_len"
+.Fa "Dwarf_Ptr *block_ptr"
+.Fa "Dwarf_Addr *row_pc"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_fde_info_for_cfa_reg3
+retrieves the CFA register rule for a given program counter address
+from the register rule table associated with an FDE descriptor.
+.Pp
+Argument
+.Ar fde
+should reference a valid DWARF FDE descriptor.
+.Pp
+Argument
+.Ar pc
+should hold the program counter address to be used to locate the
+desired register rule row.
+.Pp
+On successful execution,
+.Fn dwarf_get_fde_info_for_cfa_reg3
+stores information about the CFA register rule found into the locations
+pointed to by the arguments
+.Ar type ,
+.Ar offset_relevant ,
+.Ar register_num ,
+.Ar offset_or_block_len ,
+.Ar block_ptr
+and
+.Ar row_pc .
+.Pp
+Argument
+.Ar type
+should point to a location which will hold the type code of the
+register rule found.
+The returned value is one of the
+.Dv DW_EXPR_*
+contants defined in the header file
+.In libdwarf.h .
+.Pp
+If there is an offset value associated with the CFA register rule,
+the location pointed to by argument
+.Ar offset_relevant
+will be set to 1.
+.Pp
+Argument
+.Ar register_num
+should point to a location which will hold the register number associated
+with the CFA register rule.
+.Pp
+If the CFA register rule is of type
+.Dv DW_EXPR_OFFSET
+or
+.Dv DW_EXPR_VAL_OFFSET ,
+the location pointed to by argument
+.Ar offset_or_block_len
+will be set to the offset value associated with the register rule,
+or to 0 if the register rule does not have an offset value.
+If the type code is
+.Dv DW_EXPR_EXPRESSION
+or
+.Dv DW_EXPR_VAL_EXPRESSION ,
+the location pointed to by argument
+.Ar offset_or_block_len
+will be set to the length in bytes of the DWARF expression block
+associated with the register rule.
+.Pp
+Argument
+.Ar block_ptr
+should point to a location which will be set to a pointer to the
+content of the DWARF expression block associated with the CFA register
+rule.
+.Pp
+Argument
+.Ar row_pc
+should point to a location which will be set to the lowest program
+counter address associated with the register rule found.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to return an error descriptor in case
+of an error.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_get_fde_info_for_cfa_reg3
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_fde_info_for_cfa_reg3
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_PC_NOT_IN_FDE_RANGE"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar block_ptr ,
+.Ar fde ,
+.Ar offset_or_block_len ,
+.Ar offset_relevant ,
+.Ar register_num ,
+.Ar row_pc ,
+or
+.Ar type
+was NULL.
+.It Bq Er DW_DLE_PC_NOT_IN_FDE_RANGE
+The program counter value provided in argument
+.Ar pc
+did not fall in the range covered by argument
+.Ar fde .
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_fde_at_pc 3 ,
+.Xr dwarf_get_fde_info_for_all_regs 3 ,
+.Xr dwarf_get_fde_info_for_all_regs3 3 ,
+.Xr dwarf_get_fde_info_for_reg 3 ,
+.Xr dwarf_get_fde_info_for_reg3 3 ,
+.Xr dwarf_get_fde_n 3 ,
+.Xr dwarf_set_frame_cfa_value 3 ,
+.Xr dwarf_set_frame_rule_table_size 3 ,
+.Xr dwarf_set_frame_rule_initial_value 3 ,
+.Xr dwarf_set_frame_same_value 3 ,
+.Xr dwarf_set_frame_undefined_value 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_fde_info_for_reg.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,156 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_fde_info_for_reg.3 3181 2015-04-10 13:22:51Z emaste $
+.\"
+.Dd June 4, 2011
+.Os
+.Dt DWARF_GET_FDE_INFO_FOR_REG 3
+.Sh NAME
+.Nm dwarf_get_fde_info_for_reg
+.Nd retrieve register rule
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_fde_info_for_reg
+.Fa "Dwarf_Fde fde"
+.Fa "Dwarf_Half table_column"
+.Fa "Dwarf_Addr pc"
+.Fa "Dwarf_Signed *offset_relevant"
+.Fa "Dwarf_Signed *register_num"
+.Fa "Dwarf_Signed *offset"
+.Fa "Dwarf_Addr *row_pc"
+.Fa "Dwarf_Error *error"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_fde_info_for_reg
+retrieves a register rule from the register rule table associated with
+a given FDE descriptor, given a program counter address and rule
+column number.
+.Pp
+Argument
+.Ar fde
+should reference a valid DWARF FDE descriptor.
+.Pp
+Arugment
+.Ar table_column
+should hold the column number of the register rule desired.
+.Pp
+Argument
+.Ar pc
+should hold the program counter address to be used to locate the
+desired register rule row.
+.Pp
+On successful execution,
+.Fn dwarf_get_fde_info_for_reg
+stores information about the register rule found into the locations
+pointed to by the arguments
+.Ar offset_relevant ,
+.Ar register_num ,
+.Ar offset
+and
+.Ar row_pc .
+.Pp
+If there is an offset value associated with the register rule,
+the location pointed to by argument
+.Ar offset_relevant
+will be set to 1.
+.Pp
+Argument
+.Ar register_num
+should point to a location which will hold the register number associated
+with the register rule.
+.Pp
+Argument
+.Ar offset
+should point to a location which will be set to the offset value
+associated with the register rule, or to 0 if the register rule
+does not have an offset value.
+.Pp
+Argument
+.Ar row_pc
+should point to a location which will be set to the lowest program
+counter address associated with the register rule found.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to return an error descriptor in case
+of an error.
+.Ss COMPATIBILITY
+Function
+.Fn dwarf_get_fde_info_for_reg
+is deprecated since it only supports DWARF2 frame sections.
+Applications should instead use function
+.Xr dwarf_get_fde_info_for_reg3 3
+which supports both DWARF2 and DWARF3 frame sections.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_get_fde_info_for_reg
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_fde_info_for_reg
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_FRAME_TABLE_COL_BAD"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar fde ,
+.Ar offset_relevant ,
+.Ar register_num ,
+.Ar offset
+or
+.Ar row_pc
+was NULL.
+.It Bq Er DW_DLE_FRAME_TABLE_COL_BAD
+The column number provided in argument
+.Ar table_column
+was too large.
+.It Bq Er DW_DLE_PC_NOT_IN_FDE_RANGE
+The program counter value provided in argument
+.Ar pc
+did not fall in the range covered by argument
+.Ar fde .
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_fde_at_pc 3 ,
+.Xr dwarf_get_fde_info_for_all_regs 3 ,
+.Xr dwarf_get_fde_info_for_all_regs3 3 ,
+.Xr dwarf_get_fde_info_for_cfa_reg3 3 ,
+.Xr dwarf_get_fde_info_for_reg3 3 ,
+.Xr dwarf_get_fde_n 3 ,
+.Xr dwarf_set_frame_cfa_value 3 ,
+.Xr dwarf_set_frame_rule_table_size 3 ,
+.Xr dwarf_set_frame_rule_initial_value 3 ,
+.Xr dwarf_set_frame_same_value 3 ,
+.Xr dwarf_set_frame_undefined_value 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_fde_info_for_reg3.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,214 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_fde_info_for_reg3.3 2122 2011-11-09 15:35:14Z jkoshy $
+.\"
+.Dd November 9, 2011
+.Os
+.Dt DWARF_GET_FDE_INFO_FOR_REG3 3
+.Sh NAME
+.Nm dwarf_get_fde_info_for_reg3
+.Nd retrieve register rule
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_fde_info_for_reg3
+.Fa "Dwarf_Fde fde"
+.Fa "Dwarf_Half table_column"
+.Fa "Dwarf_Addr pc"
+.Fa "Dwarf_Small *type"
+.Fa "Dwarf_Signed *offset_relevant"
+.Fa "Dwarf_Signed *register_num"
+.Fa "Dwarf_Signed *offset_or_block_len"
+.Fa "Dwarf_Ptr *block_ptr"
+.Fa "Dwarf_Addr *row_pc"
+.Fa "Dwarf_Error *error"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_fde_info_for_reg3
+retrieves a register rule from the register rule table associated with
+a given FDE descriptor, given a program counter address and rule
+column number.
+.Pp
+Argument
+.Ar fde
+should reference a valid DWARF FDE descriptor.
+.Pp
+Arugment
+.Ar table_column
+should hold the column number of the register rule desired.
+.Pp
+Argument
+.Ar pc
+should hold the program counter address to be used to locate the
+desired register rule row.
+.Pp
+On successful execution,
+.Fn dwarf_get_fde_info_for_reg3
+stores information about the register rule found into the locations
+pointed to by the arguments
+.Ar type ,
+.Ar offset_relevant ,
+.Ar register_num ,
+.Ar offset_or_block_len ,
+.Ar block_ptr
+and
+.Ar row_pc .
+.Pp
+Argument
+.Ar type
+should point to a location which will hold the type code of the
+register rule found.
+The returned value is one of the
+.Dv DW_EXPR_*
+contants defined in the header file
+.In libdwarf.h .
+.Pp
+If there is an offset value associated with the register rule,
+the location pointed to by argument
+.Ar offset_relevant
+will be set to 1.
+.Pp
+Argument
+.Ar register_num
+should point to a location which will hold the register number associated
+with the register rule.
+.Pp
+If the register rule is of type
+.Dv DW_EXPR_OFFSET
+or
+.Dv DW_EXPR_VAL_OFFSET ,
+the location pointed to by argument
+.Ar offset_or_block_len
+will be set to the offset value associated with the register rule,
+or to 0 if the register rule does not have an offset value.
+If the type code is
+.Dv DW_EXPR_EXPRESSION
+or
+.Dv DW_EXPR_VAL_EXPRESSION ,
+the location pointed to by argument
+.Ar offset_or_block_len
+will be set to the length in bytes of the DWARF expression block
+associated with the register rule.
+.Pp
+Argument
+.Ar block_ptr
+should point to a location which will be set to a pointer to the
+content of the DWARF expression block associated with the register
+rule.
+.Pp
+Argument
+.Ar row_pc
+should point to a location which will be set to the lowest program
+counter address associated with the register rule found.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to return an error descriptor in case
+of an error.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_get_fde_info_for_reg3
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_fde_info_for_reg3
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_FRAME_TABLE_COL_BAD"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar block_ptr ,
+.Ar fde ,
+.Ar offset_or_block_len ,
+.Ar offset_relevant ,
+.Ar register_num ,
+.Ar row_pc ,
+or
+.Ar type
+was NULL.
+.It Bq Er DW_DLE_FRAME_TABLE_COL_BAD
+The column number provided in argument
+.Ar table_column
+was too large.
+.It Bq Er DW_DLE_PC_NOT_IN_FDE_RANGE
+The program counter value provided in argument
+.Ar pc
+did not fall in the range covered by argument
+.Ar fde .
+.El
+.Sh EXAMPLE
+To retrieve the register rules at column 3 from a rule table
+associated with a FDE descriptor:
+.Bd -literal -offset indent
+Dwarf_Fde fde;
+Dwarf_Off fde_offset, cie_offset;
+Dwarf_Unsigned func_len, fde_length;
+Dwarf_Signed cie_index, offset_relevant, register_num;
+Dwarf_Signed offset_or_block_len;
+Dwarf_Addr low_pc, row_pc;
+Dwarf_Ptr fde_addr, block_ptr;
+Dwarf_Small type;
+Dwarf_Error de;
+
+/* ... assuming `fde` references a valid FDE descriptor... */
+if (dwarf_get_fde_range(fde, &low_pc, &func_len, &fde_addr,
+    &fde_length, &cie_offset, &cie_index, &fde_offset,
+    &de) != DW_DLV_OK)
+	errx(EXIT_FAILURE, "dwarf_get_fde_range failed: %s",
+	    dwarf_errmsg(de));
+
+/* Iterate all the table rows. */
+for (pc = low_pc; pc < low_pc + func_len; pc++) {
+	if (dwarf_get_fde_info_for_reg3(fde, 3, pc, &type,
+	    &offset_relevant, &register_num, &offset_or_block_len,
+	    &block_ptr, &row_pc, &de) != DW_DLV_OK) {
+		warnx("dwarf_get_fde_info_for_reg3 failed: %s",
+		    dwarf_errmsg(de));
+		continue;
+	}
+	/* ... use the retrieved register rule ... */
+}
+.Ed
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_fde_at_pc 3 ,
+.Xr dwarf_get_fde_info_for_all_regs 3 ,
+.Xr dwarf_get_fde_info_for_all_regs3 3 ,
+.Xr dwarf_get_fde_info_for_cfa_reg3 3 ,
+.Xr dwarf_get_fde_info_for_reg 3 ,
+.Xr dwarf_get_fde_n 3 ,
+.Xr dwarf_set_frame_cfa_value 3 ,
+.Xr dwarf_set_frame_rule_table_size 3 ,
+.Xr dwarf_set_frame_rule_initial_value 3 ,
+.Xr dwarf_set_frame_same_value 3 ,
+.Xr dwarf_set_frame_undefined_value 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_fde_instr_bytes.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,113 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_fde_instr_bytes.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd May 23, 2011
+.Os
+.Dt DWARF_GET_FDE_INSTR_BYTES 3
+.Sh NAME
+.Nm dwarf_get_fde_instr_bytes
+.Nd retrieve instructions from FDE descritpor
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_fde_instr_bytes
+.Fa "Dwarf_Fde fde"
+.Fa "Dwarf_Ptr *ret_inst"
+.Fa "Dwarf_Unsigned *ret_len"
+.Fa "Dwarf_Error *error"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_fde_instr_bytes
+retrieves instruction bytes from a given FDE descriptor.
+.Pp
+Argument
+.Ar fde
+should reference a valid DWARF FDE descriptor.
+.Pp
+Argument
+.Ar ret_inst
+should point to a location that will be set to a pointer
+to an array of bytes containing the instructions of the
+FDE descriptor.
+.Pp
+Argument
+.Ar ret_len
+should point to a location that will hold the length in
+bytes of the instructions returned in argument
+.Ar ret_inst .
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Pp
+Applications can use the function
+.Xr dwarf_expand_frame_instructions 3
+to parse and expand the returned instruction bytes into an array of
+.Vt Dwarf_Frame_Op
+descriptors.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_get_fde_instr_bytes
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_fde_instr_bytes
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar fde ,
+.Ar ret_inst
+or
+.Ar ret_len
+was NULL.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_expand_frame_instructions 3 ,
+.Xr dwarf_get_cie_info 3 ,
+.Xr dwarf_get_cie_index 3 ,
+.Xr dwarf_get_cie_of_fde ,
+.Xr dwarf_get_fde_at_pc 3 ,
+.Xr dwarf_get_fde_info_for_all_regs 3 ,
+.Xr dwarf_get_fde_info_for_all_regs3 3 ,
+.Xr dwarf_get_fde_info_for_cfa_reg3 3 ,
+.Xr dwarf_get_fde_info_for_reg 3 ,
+.Xr dwarf_get_fde_info_for_reg3 3 ,
+.Xr dwarf_get_fde_list 3 ,
+.Xr dwarf_get_fde_list_eh 3 ,
+.Xr dwarf_get_fde_n 3 ,
+.Xr dwarf_get_fde_range 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_fde_list.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,218 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_fde_list.3 2122 2011-11-09 15:35:14Z jkoshy $
+.\"
+.Dd November 9, 2011
+.Os
+.Dt DWARF_GET_FDE_LIST 3
+.Sh NAME
+.Nm dwarf_get_fde_list
+.Nd retrieve frame information
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_fde_list
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Cie **cie_list"
+.Fa "Dwarf_Signed *cie_count"
+.Fa "Dwarf_Fde **fde_list"
+.Fa "Dwarf_Signed *fde_count"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_get_fde_list_eh
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Cie **cie_list"
+.Fa "Dwarf_Signed *cie_count"
+.Fa "Dwarf_Fde **fde_list"
+.Fa "Dwarf_Signed *fde_count"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+These functions retrieve frame related information for the specified
+DWARF debug context.
+.Pp
+Function
+.Fn dwarf_get_fde_list
+retrieves frame information from the DWARF section named
+.Dq ".debug_frame" .
+For objects containing GNU style C++ exception handling
+information, the function
+.Fn dwarf_get_fde_list_eh
+retrieves frame information from the section named
+.Dq ".eh_frame" .
+.Pp
+Frame information is returned using opaque descriptors
+of type
+.Vt Dwarf_Cie
+and
+.Vt Dwarf_Fde .
+Applications need to use the other frame related functions in the
+DWARF(3) API set to retrieve the information contained in these
+descriptors.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF debug context allocated using
+.Xr dwarf_init 3 .
+.Pp
+Argument
+.Ar cie_list
+should point to a location that will be set to a pointer to an array
+of
+.Vt Dwarf_Cie
+descriptors.
+.Pp
+Argument
+.Ar cie_count
+should point to a location that will be set to the number of
+.Vt Dwarf_Cie
+descriptors returned.
+.Pp
+Argument
+.Ar fde_list
+should point to a location that will be set to a pointer to an array
+of
+.Vt Dwarf_Fde
+descriptors.
+.Pp
+Argument
+.Ar fde_count
+should point to a location that will be set to the number of
+.Vt Dwarf_Fde
+descriptors returned.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Ss Memory Management
+The memory areas used for the arrays returned in arguments
+.Ar cie_list
+and
+.Ar fde_list
+are owned by the
+.Lb libdwarf .
+Application code should not attempt to directly free these areas.
+Portable applications should instead use the
+.Xr dwarf_fde_cie_list_dealloc 3
+function to indicate that these memory areas may be freed.
+.Sh RETURN VALUES
+On success, these functions returns
+.Dv DW_DLV_OK .
+They return
+.Dv DW_DLV_NO_ENTRY
+if there is no frame information associated with the given DWARF
+debug context.
+In case of an error, they return
+.Dv DW_DLV_ERROR
+and set the argument
+.Ar err .
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Va dbg ,
+.Va cie_list ,
+.Va cie_count ,
+.Va fde_list
+or
+.Va fde_count
+was NULL.
+.It Bq Er DW_DLE_NO_ENTRY
+There is no frame information associated with the giving DWARF debug
+context.
+.El
+.Sh EXAMPLE
+To obtain frame information from the
+.Dq ".debug_frame"
+section, use:
+.Bd -literal -offset indent
+Dwarf_Debug dbg;
+Dwarf_Cie *cie_list, cie;
+Dwarf_Fde *fde_list, fde;
+Dwarf_Off fde_offset, cie_offset;
+Dwarf_Unsigned func_len, fde_length, fde_instlen;
+Dwarf_Signed cie_count, fde_count, cie_index;
+Dwarf_Addr low_pc;
+Dwarf_Ptr fde_addr, fde_inst, cie_inst;
+Dwarf_Error de;
+int i;
+
+if (dwarf_get_fde_list(dbg, &cie_list, &cie_count,
+    &fde_list, &fde_count, &de) != DW_DLV_OK) {
+	errx(EXIT_FAILURE, "dwarf_get_fde_list failed: %s",
+	    dwarf_errmsg(de));
+}
+
+for (i = 0; i < fde_count; i++) {
+	if (dwarf_get_fde_n(fde_list, i, &fde, &de) != DW_DLV_OK) {
+		warnx("dwarf_get_fde_n failed: %s",
+		    dwarf_errmsg(de));
+		continue;
+	}
+	if (dwarf_get_cie_of_fde(fde, &cie, &de) != DW_DLV_OK) {
+		warnx("dwarf_get_fde_n failed: %s",
+		    dwarf_errmsg(de));
+		continue;
+	}
+	if (dwarf_get_fde_range(fde, &low_pc, &func_len, &fde_addr,
+	    &fde_length, &cie_offset, &cie_index, &fde_offset,
+	    &de) != DW_DLV_OK) {
+		warnx("dwarf_get_fde_range failed: %s",
+		    dwarf_errmsg(de));
+		continue;
+	}
+	if (dwarf_get_fde_instr_bytes(fde, &fde_inst, &fde_instlen,
+	    &de) != DW_DLV_OK) {
+		warnx("dwarf_get_fde_instr_bytes failed: %s",
+		    dwarf_errmsg(de));
+		continue;
+	}
+
+	/* ... Use the retrieved frame information ... */
+}
+
+/* Indicate that the returned arrays may be freed. */
+dwarf_fde_cie_list_dealloc(dbg, cie_list, cie_count, fde_list,
+    fde_count);
+.Ed
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_cie_index 3 ,
+.Xr dwarf_get_cie_of_fde 3 ,
+.Xr dwarf_get_fde_at_pc 3 ,
+.Xr dwarf_get_fde_instr_bytes 3 ,
+.Xr dwarf_get_fde_n 3 ,
+.Xr dwarf_get_fde_range 3 ,
+.Xr dwarf_fde_cie_list_dealloc 3 ,
+.Xr dwarf_set_frame_cfa_value 3 ,
+.Xr dwarf_set_frame_rule_table_size 3 ,
+.Xr dwarf_set_frame_rule_initial_value 3 ,
+.Xr dwarf_set_frame_same_value 3 ,
+.Xr dwarf_set_frame_undefined_value 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_fde_n.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,111 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_fde_n.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd May 14, 2011
+.Os
+.Dt DWARF_GET_FDE_N 3
+.Sh NAME
+.Nm dwarf_get_fde_n
+.Nd retrieve FDE descriptor
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_fde_n
+.Fa "Dwarf_Fde *fdelist"
+.Fa "Dwarf_Unsigned fde_index"
+.Fa "Dwarf_Fde *ret_fde"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_fde_n
+retrieves an FDE descriptor from an array of FDE descriptors.
+.Pp
+Argument
+.Ar fdelist
+should point to an array of FDE descriptors, as returned by the functions
+.Xr dwarf_get_fde_list 3
+or
+.Xr dwarf_get_fde_list_eh 3 .
+.Pp
+Argument
+.Ar fde_index
+specifies the 0-based index of the desired FDE descriptor.
+.Pp
+Argument
+.Ar ret_fde
+should point to a location that will hold the returned FDE descriptor.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_get_fde_n
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+It returns
+.Dv DW_DLV_NO_ENTRY
+if the FDE descriptor index specified by argument
+.Ar fde_index
+is out of range.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_fde_n
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_NO_ENTRY"
+.It Bq Er DW_DLE_ARGUMENT
+Either of the arguments
+.Ar fdelist
+or
+.Ar ret_fde
+was NULL.
+.It Bq Er DW_DLE_NO_ENTRY
+The FDE descriptor index specified by argument
+.Ar fde_index
+was out of range.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_cie_of_fde 3 ,
+.Xr dwarf_get_fde_at_pc 3 ,
+.Xr dwarf_get_fde_info_for_all_regs 3 ,
+.Xr dwarf_get_fde_info_for_all_regs3 3 ,
+.Xr dwarf_get_fde_info_for_cfa_reg3 3 ,
+.Xr dwarf_get_fde_info_for_reg 3 ,
+.Xr dwarf_get_fde_info_for_reg3 3 ,
+.Xr dwarf_get_fde_instr_bytes 3 ,
+.Xr dwarf_get_fde_list 3 ,
+.Xr dwarf_get_fde_list_eh 3 ,
+.Xr dwarf_get_fde_range 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_fde_range.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,149 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_fde_range.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd May 22, 2011
+.Os
+.Dt DWARF_GET_FDE_RANGE 3
+.Sh NAME
+.Nm dwarf_get_fde_range
+.Nd retrieve range information from an FDE descriptor
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_fde_range
+.Fa "Dwarf_Fde fde"
+.Fa "Dwarf_Addr *low_pc"
+.Fa "Dwarf_Unsigned *func_len"
+.Fa "Dwarf_Ptr *fde_bytes"
+.Fa "Dwarf_Unsigned *fde_byte_len"
+.Fa "Dwarf_Off *cie_offset"
+.Fa "Dwarf_Signed *cie_index"
+.Fa "Dwarf_Off *fde_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_fde_range
+retrieves range and offset information from a given FDE descriptor.
+.Pp
+Argument
+.Ar fde
+should reference a valid DWARF FDE descriptor.
+.Pp
+Argument
+.Ar low_pc
+should point to a location that will be set to the lowest
+program counter address covered by the FDE descriptor.
+.Pp
+Argument
+.Ar func_len
+should point to a location that will hold the length in bytes of
+the address range covered by the FDE descriptor.
+.Pp
+Argument
+.Ar fde_bytes
+should point to a location that will be set to a pointer to the
+content of the FDE descriptor itself.
+.Pp
+Argument
+.Ar fde_byte_len
+should point to a location that will hold the length in bytes of
+the FDE descriptor itself.
+.Pp
+Argument
+.Ar cie_offset
+should point to a location that will be set to the offset, relative to
+the DWARF
+.Dq ".debug_frame"
+section, of the CIE descriptor associated with the given FDE
+descriptor.
+.Pp
+Argument
+.Ar cie_index
+should point to a location that will hold the index of the CIE
+descriptor associated with the FDE descriptor.
+The returned value is a zero-based index into the array of CIE
+descriptors returned by a prior call to functions
+.Xr dwarf_get_fde_list 3
+or
+.Xr dwarf_get_fde_list_eh 3 .
+.Pp
+Argument
+.Ar fde_offset
+should point to a location that will be set to the offset, relative to
+the DWARF
+.Dq ".debug_frame"
+section, of the FDE descriptor.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_get_fde_range
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_fde_range
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar fde ,
+.Ar low_pc ,
+.Ar func_len ,
+.Ar fde_bytes ,
+.Ar fde_byte_len ,
+.Ar cie_offset ,
+.Ar cie_index
+or
+.Ar fde_offset
+was NULL.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_cie_info 3 ,
+.Xr dwarf_get_cie_index 3 ,
+.Xr dwarf_get_cie_of_fde ,
+.Xr dwarf_get_fde_at_pc 3 ,
+.Xr dwarf_get_fde_info_for_all_regs 3 ,
+.Xr dwarf_get_fde_info_for_all_regs3 3 ,
+.Xr dwarf_get_fde_info_for_cfa_reg3 3 ,
+.Xr dwarf_get_fde_info_for_reg 3 ,
+.Xr dwarf_get_fde_info_for_reg3 3 ,
+.Xr dwarf_get_fde_instr_bytes 3 ,
+.Xr dwarf_get_fde_list 3 ,
+.Xr dwarf_get_fde_list_eh 3 ,
+.Xr dwarf_get_fde_n 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_form_class.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,87 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_form_class.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd June 26, 2011
+.Os
+.Dt DWARF_GET_FORM_CLASS 3
+.Sh NAME
+.Nm dwarf_get_form_class
+.Nd retrieve the form class of an attribute
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft enum Dwarf_Form_Class
+.Fo dwarf_get_form_class
+.Fa "Dwarf_Half dwversion"
+.Fa "Dwarf_Half attr"
+.Fa "Dwarf_Half offset_size"
+.Fa "Dwarf_Half form"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_form_class
+returns the class of the form of a DWARF attribute.
+.Pp
+Argument
+.Ar dwversion
+should specify the version number of DWARF specification
+to use: 2 for DWARF2, 3 for DWARF3 and 4 for DWARF4.
+.Pp
+Argument
+.Ar attr
+should hold the attribute code of the attribute, i.e., one of the
+.Li DW_AT_*
+values defined in
+.In libdwarf.h .
+.Pp
+Argument
+.Ar offset_size
+should hold the size of a DWARF offset for the relevant compilation
+unit.
+.Pp
+Argument
+.Ar form
+should hold the form code of the attribute.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_get_form_class
+returns the form class code, which is one of the
+.Dv DW_FORM_CLASS_*
+contants defined in header file
+.In libdwarf.h .
+If the function was not able to determine the form class of the
+attribute, it returns the special form class code
+.Dv DW_FORM_CLASS_UNKNOWN .
+.Sh ERRORS
+Function
+.Fn dwarf_get_form_class
+does not return an error.
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_attr 3 ,
+.Xr dwarf_whatattr 3 ,
+.Xr dwarf_whatform 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_funcs.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,215 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_funcs.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd April 10, 2011
+.Os
+.Dt DWARF_GET_FUNCS 3
+.Sh NAME
+.Nm dwarf_get_funcs ,
+.Nm dwarf_func_cu_offset ,
+.Nm dwarf_func_die_offset ,
+.Nm dwarf_func_name_offsets ,
+.Nm dwarf_funcname
+.Nd retrieve information about static functions
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_funcs
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Func **funcs"
+.Fa "Dwarf_Signed *nfuncs"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_func_cu_offset
+.Fa "Dwarf_Func func"
+.Fa "Dwarf_Off *cu_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_func_die_offset
+.Fa "Dwarf_Func func"
+.Fa "Dwarf_Off *die_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_func_name_offsets
+.Fa "Dwarf_Func func"
+.Fa "char **name"
+.Fa "Dwarf_Off *die_offset"
+.Fa "Dwarf_Off *cu_die_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_funcname
+.Fa "Dwarf_Func func"
+.Fa "char **name"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+These functions retrieve information about static functions from the
+lookup tables in the (SGI-specific)
+.Dq ".debug_funcnames"
+section.
+Information about these functions is returned using opaque descriptors
+of type
+.Vt Dwarf_Func .
+Applications need to use the functions described below to retrieve
+the name and offset information contained in these descriptors.
+.Pp
+Function
+.Fn dwarf_get_funcs
+retrieves descriptors for all the static functions associated with the
+DWARF debug context specified by argument
+.Ar dbg .
+The argument
+.Ar funcs
+should point to a location that will be set to a pointer to an array
+of
+.Vt Dwarf_Func
+descriptors.
+The argument
+.Ar nfuncs
+should point to a location that will be set to the number of
+descriptors returned.
+.Pp
+Function
+.Fn dwarf_func_cu_offset
+returns the offset, relative to the
+.Dq ".debug_info"
+section, of the compilation unit that contains the debugging
+information entry associated with the argument
+.Ar func .
+Argument
+.Ar cu_offset
+should point to a location that will hold the returned offset.
+.Pp
+Function
+.Fn dwarf_func_die_offset
+retrieves the offset, relative to the
+.Dq ".debug_info"
+section, of the debugging information entry associated with the
+argument
+.Ar func ,
+and stores it into the location pointed to by the argument
+.Ar die_offset .
+.Pp
+Function
+.Fn dwarf_func_name_offsets
+retrieves the name and offsets for the debugging information entry for
+argument
+.Ar func .
+Argument
+.Ar name
+should point to a location which will be set to a pointer to a
+NUL-terminated string containing the name of the associated debugging
+information entry.
+Argument
+.Ar die_offset
+should point to a location which will be set to the offset, relative
+to the
+.Dq ".debug_info"
+section, of the associated debugging information entry.
+Argument
+.Ar cu_die_offset
+should point to a location which will be set to the offset, relative
+to the
+.Dq ".debug_info"
+section, of the first debugging information entry in the compilation
+unit associated with argument
+.Ar func .
+.Pp
+Function
+.Fn dwarf_funcname
+sets the location pointed to by argument
+.Ar name
+to a pointer to a NUL-terminated string holding the name of the
+debugging information entry associated with the argument
+.Ar func .
+.Ss Memory Management
+The memory area used for the array of
+.Vt Dwarf_Func
+descriptors returned in argument
+.Ar funcs
+by function
+.Fn dwarf_get_funcs
+is owned by the
+.Lb libdwarf .
+Application code should not attempt to directly free this pointer.
+Portable code should instead use the function
+.Xr dwarf_funcs_dealloc 3
+to indicate that the memory area may be freed.
+.Pp
+The memory area used for the string returned in the
+.Ar name
+argument to functions
+.Fn dwarf_func_name_offsets
+and
+.Fn dwarf_funcname
+is owned by the
+.Lb libdwarf .
+Portable code should indicate that the memory area can
+be freed using the
+.Xr dwarf_dealloc 3
+function.
+.Ss Error Returns
+If argument
+.Ar err
+is not NULL, these functions will use it to store error information,
+in case of an error.
+.Sh RETURN VALUES
+On success, these functions returns
+.Dv DW_DLV_OK .
+In case of an error, they return
+.Dv DW_DLV_ERROR
+and set the argument
+.Ar err .
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Va cu_die_offset ,
+.Va cu_offset ,
+.Va dbg ,
+.Va die_offset ,
+.Va func ,
+.Va funcs ,
+.Va name ,
+or
+.Va nfuncs
+was NULL.
+.It Bq Er DW_DLE_NO_ENTRY
+The DWARF debugging context referenced by argument
+.Ar dbg
+did not contain information about static functions.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_cu_die_offset_given_cu_header_offset 3 ,
+.Xr dwarf_funcs_dealloc 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_globals.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,211 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_globals.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd April 2, 2011
+.Os
+.Dt DWARF_GET_GLOBALS 3
+.Sh NAME
+.Nm dwarf_get_globals ,
+.Nm dwarf_global_cu_offset ,
+.Nm dwarf_global_die_offset ,
+.Nm dwarf_global_name_offsets ,
+.Nm dwarf_globname
+.Nd retrieve information about global objects
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_globals
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Global **globals"
+.Fa "Dwarf_Signed *nglobals"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_global_cu_offset
+.Fa "Dwarf_Global global"
+.Fa "Dwarf_Off *cu_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_global_die_offset
+.Fa "Dwarf_Global global"
+.Fa "Dwarf_Off *die_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_global_name_offsets
+.Fa "Dwarf_Global global"
+.Fa "char **name"
+.Fa "Dwarf_Off *die_offset"
+.Fa "Dwarf_Off *cu_die_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_globname
+.Fa "Dwarf_Global global"
+.Fa "char **name"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+These functions retrieve information about global symbols from the
+lookup tables in the
+.Dq ".debug_pubnames"
+DWARF section.
+Information about these global symbols is returned using opaque descriptors
+of type
+.Vt Dwarf_Global .
+Applications need to use the functions described below to retrieve the
+name and the offsets for these descriptors.
+.Pp
+Function
+.Fn dwarf_get_globals
+retrieves descriptors for all the global symbols associated with the
+DWARF debug context specified by argument
+.Ar dbg .
+The argument
+.Ar globals
+should point to a location that will be set to a pointer to an array
+of
+.Vt Dwarf_Global
+descriptors.
+The argument
+.Ar nglobals
+should point to a location that will be set to the number of
+descriptors returned.
+.Pp
+Function
+.Fn dwarf_global_cu_offset
+returns the section-relative offset, relative to the
+.Dq ".debug_info"
+section, of the compilation unit that contains the debugging
+information entry associated with the argument
+.Ar global .
+Argument
+.Ar cu_offset
+should point to a location that will hold the returned offset.
+.Pp
+Function
+.Fn dwarf_global_die_offset
+retrieves the section-relative offset, relative to the
+.Dq ".debug_info"
+section, of the debugging information entry associated with the
+argument
+.Ar global ,
+and stores it into the location pointed to by the argument
+.Ar die_offset .
+.Pp
+Function
+.Fn dwarf_global_name_offsets
+retrieves the name and the offsets for the debugging information
+entry for argument
+.Ar global .
+Argument
+.Ar name
+should point to a location which will be set to a pointer to a
+NUL-terminated string containing the name of the associated debugging
+information entry.
+Argument
+.Ar die_offset
+should point to a location which will be set to a section-relative
+offset, relative to the
+.Dq ".debug_info"
+section, of the associated debugging information entry.
+Argument
+.Ar cu_die_offset
+should point to a location which will be set to a
+section-relative offset, relative to the
+.Dq ".debug_info"
+section, of the first debugging information entry in
+the compilation unit associated with argument
+.Ar global .
+.Pp
+Function
+.Fn dwarf_globname
+sets the location pointed to by argument
+.Ar name
+to a pointer to a NUL-terminated string holding the name of the
+debugging information entry associated with the argument
+.Ar global .
+.Ss Memory Management
+The memory area used for the array of
+.Vt Dwarf_Global
+descriptors returned in argument
+.Ar globals
+by function
+.Fn dwarf_get_globals
+is owned by the
+.Lb libdwarf .
+Application code should not attempt to directly free this pointer.
+Portable code should instead use the function
+.Xr dwarf_globals_dealloc 3
+to indicate that the memory area may be freed.
+.Pp
+The memory area used for the string returned in the
+.Ar name
+argument to functions
+.Fn dwarf_globname
+and
+.Fn dwarf_global_name_offsets
+is owned by the
+.Lb libdwarf .
+Portable code should use the
+.Xr dwarf_dealloc 3
+function to indicate that the memory area may be freed.
+.Ss Error Returns
+If argument
+.Ar err
+is not NULL, these functions will use it to store error information,
+in case of an error.
+.Sh RETURN VALUES
+On success, these functions returns
+.Dv DW_DLV_OK .
+In case of an error, they return
+.Dv DW_DLV_ERROR
+and set the argument
+.Ar err .
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Va cu_die_offset ,
+.Va cu_offset ,
+.Va dbg ,
+.Va die_offset ,
+.Va global ,
+.Va globals ,
+.Va name ,
+or
+.Va nglobals
+was NULL.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_dealloc 3 ,
+.Xr dwarf_get_cu_die_offset_given_cu_header_offset 3 ,
+.Xr dwarf_globals_dealloc 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_loclist_entry.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,156 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_loclist_entry.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd July 6, 2011
+.Os
+.Dt DWARF_GET_LOCLIST_ENTRY 3
+.Sh NAME
+.Nm dwarf_get_loclist_entry
+.Nd retrieve DWARF location list entry
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_loclist_entry
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Unsigned offset"
+.Fa "Dwarf_Addr *hipc"
+.Fa "Dwarf_Addr *lopc"
+.Fa "Dwarf_Ptr *data"
+.Fa "Dwarf_Unsigned *entry_len"
+.Fa "Dwarf_Unsigned *next_entry"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_loclist_entry
+retrieves a location list entry from the DWARF section
+.Dq ".debug_loc" .
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF debug context allocated using
+.Xr dwarf_init 3 .
+.Pp
+Argument
+.Ar offset
+is an offset, relative to the
+.Dq ".debug_loc"
+section, to the start of the desired location list entry.
+.Pp
+Argument
+.Ar hipc
+should point to a location which will hold the offset, relative to the
+base address of the location list entry, of the highest program
+counter value for the entry.
+.Pp
+Argument
+.Ar lowpc
+should point to a location which will hold the offset, relative to the
+base address of the location list entry, of the lowest program counter
+value for the entry.
+.Pp
+Argument
+.Ar data
+should point to a location which will be set to a pointer to the location
+list data.
+.Pp
+Argument
+.Ar entry_len
+should point to a location which will hold the length in bytes of the
+location list data returned in argument
+.Ar data .
+.Pp
+Argument
+.Ar next_entry
+should point to a location which will hold the offset of the next
+location list entry.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_get_loclist_entry
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+It returns
+.Dv DW_DLV_NO_ENTRY
+if there is no location list at the specified offset
+.Ar offset .
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_loclist_entry
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_NO_ENTRY"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar dbg ,
+.Ar hipc ,
+.Ar lopc ,
+.Ar data ,
+.Ar entry_len
+or
+.Ar next_entry
+was NULL.
+.It Bq Er DW_DLE_NO_ENTRY
+There is no location list at the specified offset
+.Ar offset .
+.El
+.Sh EXAMPLE
+To iterate through all the location list entries in the
+.Dq ".debug_loc"
+section, use:
+.Bd -literal -offset indent
+Dwarf_Debug dbg;
+Dwarf_Unsigned off, len, next;
+Dwarf_Addr hipc, lopc;
+Dwarf_Ptr data;
+Dwarf_Error de;
+int ret;
+
+off = 0;
+while ((ret = dwarf_get_loclist_entry(dbg, off, &hipc, &lopc, &data,
+    &len, &next, &de)) == DW_DLV_OK) {
+	/* ... use loclist entry ... */
+	off = next;
+}
+if (ret == DW_DLV_ERROR)
+	warnx("dwarf_get_loclist_entry failed: %s", dwarf_errmsg(de));
+.Ed
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_loclist 3 ,
+.Xr dwarf_loclist_n 3 ,
+.Xr dwarf_loclist_from_expr 3 ,
+.Xr dwarf_loclist_from_expr_a 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_macro_details.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,192 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_macro_details.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd March 20, 2011
+.Os
+.Dt DWARF_GET_MACRO_DETAILS 3
+.Sh NAME
+.Nm dwarf_get_macro_details
+.Nd retrieve macro information
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_macro_details
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Off offset"
+.Fa "Dwarf_Unsigned max_count"
+.Fa "Dwarf_Signed *entry_cnt"
+.Fa "Dwarf_Macro_Details **details"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_macro_details
+retrieves information about macros associated with a DWARF debug
+context.
+Information about macro entries are returned as an array of
+descriptors of type
+.Vt Dwarf_Macro_Details ,
+with each
+.Vt Dwarf_Macro_Details
+descriptor describing one macro information entry.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF debug context allocated using
+.Xr dwarf_init 3 .
+Argument
+.Ar offset
+is an offset, relative to the
+.Dq ".debug_macinfo"
+section, to the start of the desired macro information.
+Argument
+.Ar max_count
+specifies the maximum number of macro information entries
+to be returned, or 0 if all entries are to be returned.
+Argument
+.Ar entry_cnt
+should point to a location that will be set to the number
+of entries actually returned.
+Argument
+.Ar details
+should point to a location that will be set to a pointer to
+an array of
+.Vt Dwarf_Macro_Details
+descriptors.
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Pp
+.Vt Dwarf_Macro_Details
+descriptors are defined in the header file
+.In libdwarf.h ,
+and consist of the following fields:
+.Bl -tag -width ".Va dmd_fileindex" -compact
+.It Va dmd_offset
+The section-relative offset within the
+.Dq ".debug_macinfo"
+section of the macro information entry being described.
+.It Va dmd_type
+The type code of this macro information entry; one of the
+.Dv DW_MACINFO_*
+constants defined by the DWARF specification.
+.It Va dmd_lineno
+The line number associated with the macro information
+entry, or 0 if there is no applicable line number.
+.It Va dmd_fileindex
+The source file index for the macro information entry.
+This field is only meaningful when
+.Va dmd_type
+field is set to
+.Dv DW_MACINFO_start_file .
+.It Va dmd_macro
+The contents of this field is a pointer to a NUL-terminated string
+whose meaning depends on the value of the
+.Va dmd_type
+field:
+.Bl -tag -width ".Dv DW_MACINFO_vendor_ext" -compact
+.It Dv DW_MACINFO_define
+The returned string contains the macro name and value.
+.It Dv DW_MACINFO_undef
+The string holds the macro name.
+.It Dv DW_MACINFO_vendor_ext
+The
+.Va dmd_macro
+field points to a vendor defined string.
+.El
+The field is NULL for other values of
+.Va dmd_type .
+.El
+.Ss Memory Management
+The memory area used for the array of
+.Vt Dwarf_Macro_Details
+descriptors returned in argument
+.Ar details
+is owned by the
+.Lb libdwarf .
+The application should not attempt to directly free this pointer.
+Portable code should instead use
+.Fn dwarf_dealloc
+with the allocation type
+.Dv DW_DLA_STRING
+to indicate that the memory may be freed.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_get_macro_details
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+It returns
+.Dv DW_DLV_NO_ENTRY
+if there is no more macro information at the specified offset
+.Ar offset .
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_macro_details
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_NO_ENTRY"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar dbg ,
+.Ar entry_cnt
+or
+.Ar details
+was NULL.
+.It Bq Er DW_DLE_NO_ENTRY
+There is no more macro information at the specified offset
+.Ar offset .
+.El
+.Sh EXAMPLE
+To loop through all the macro information entries associated with
+a DWARF debug context:
+.Bd -literal -offset indent
+Dwarf_Debug dbg;
+Dwarf_Unsigned offset;
+Dwarf_Signed cnt;
+Dwarf_Macro_Details *md;
+Dwarf_Error de;
+
+offset = 0;
+while (dwarf_get_macro_details(dbg, offset, 0,
+    &cnt, &md, &de) == DW_DLV_OK) {
+	for (i = 0; i < cnt; i++) {
+		/* Access fields of md[i] ... */
+	}
+	offset = md[cnt - 1].dmd_offset + 1;
+}
+.Ed
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_dealloc 3 ,
+.Xr dwarf_find_macro_value_start 3 ,
+.Xr dwarf_init 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_pubtypes.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,243 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_pubtypes.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd April 4, 2011
+.Os
+.Dt DWARF_GET_PUBTYPES 3
+.Sh NAME
+.Nm dwarf_get_pubtypes ,
+.Nm dwarf_pubtype_cu_offset ,
+.Nm dwarf_pubtype_die_offset ,
+.Nm dwarf_pubtype_name_offsets ,
+.Nm dwarf_pubtypename
+.Nd retrieve information about user-defined types
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_pubtypes
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Type **types"
+.Fa "Dwarf_Signed *ntypes"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_pubtype_cu_offset
+.Fa "Dwarf_Type type"
+.Fa "Dwarf_Off *cu_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_pubtype_die_offset
+.Fa "Dwarf_Type type"
+.Fa "Dwarf_Off *die_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_pubtype_name_offsets
+.Fa "Dwarf_Type type"
+.Fa "char **name"
+.Fa "Dwarf_Off *die_offset"
+.Fa "Dwarf_Off *cu_die_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_pubtypename
+.Fa "Dwarf_Type type"
+.Fa "char **name"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+These functions retrieve information about file-scope, user-defined
+types recorded in lookup tables in the
+.Dq ".debug_pubtypes"
+DWARF section.
+Information about these types is returned using opaque descriptors
+of type
+.Vt Dwarf_Type .
+Applications need to use the functions described below to retrieve
+the name and offset information contained in these descriptors.
+.Pp
+Function
+.Fn dwarf_get_pubtypes
+retrieves descriptors for all the user-defined types associated with the
+DWARF debug context specified by argument
+.Ar dbg .
+The argument
+.Ar types
+should point to a location that will be set to a pointer to an array
+of
+.Vt Dwarf_Type
+descriptors.
+The argument
+.Ar ntypes
+should point to a location that will be set to the number of
+descriptors returned.
+.Pp
+Function
+.Fn dwarf_pubtype_cu_offset
+returns the offset, relative to the
+.Dq ".debug_info"
+section, of the compilation unit that contains the debugging
+information entry associated with the argument
+.Ar type .
+Argument
+.Ar cu_offset
+should point to a location that will hold the returned offset.
+.Pp
+Function
+.Fn dwarf_pubtype_die_offset
+retrieves the offset, relative to the
+.Dq ".debug_info"
+section, of the debugging information entry associated with the
+argument
+.Ar type ,
+and stores it into the location pointed to by the argument
+.Ar die_offset .
+.Pp
+Function
+.Fn dwarf_pubtype_name_offsets
+retrieves the name and offsets for the debugging information entry for
+argument
+.Ar type .
+Argument
+.Ar name
+should point to a location which will be set to a pointer to a
+NUL-terminated string containing the name of the associated debugging
+information entry.
+Argument
+.Ar die_offset
+should point to a location which will be set to the
+offset, relative to the
+.Dq ".debug_info"
+section, of the associated debugging information entry.
+Argument
+.Ar cu_die_offset
+should point to a location which will be set to the
+offset, relative to the
+.Dq ".debug_info"
+section, of the first debugging information entry in the compilation
+unit associated with argument
+.Ar type .
+.Pp
+Function
+.Fn dwarf_pubtypename
+sets the location pointed to by argument
+.Ar name
+to a pointer to a NUL-terminated string holding the name of the
+debugging information entry associated with the argument
+.Ar type .
+.Ss Memory Management
+The memory area used for the array of
+.Vt Dwarf_Type
+descriptors returned in argument
+.Ar types
+by function
+.Fn dwarf_get_pubtypes
+is owned by the
+.Lb libdwarf .
+Application code should not attempt to directly free this pointer.
+Portable code should instead use the function
+.Xr dwarf_types_dealloc 3
+to indicate that the memory area may be freed.
+.Pp
+The memory area used for the string returned in the
+.Ar name
+argument to functions
+.Fn dwarf_pubtype_name_offsets
+and
+.Fn dwarf_pubtypename
+is owned by the
+.Lb libdwarf .
+Portable code should indicate that the memory area can
+be freed using the
+.Xr dwarf_dealloc 3
+function.
+.Ss Error Returns
+If argument
+.Ar err
+is not NULL, these functions will use it to store error information,
+in case of an error.
+.Sh RETURN VALUES
+On success, these functions returns
+.Dv DW_DLV_OK .
+In case of an error, they return
+.Dv DW_DLV_ERROR
+and set the argument
+.Ar err .
+.Sh EXAMPLES
+To retrieve the list of file scope user-defined types and print
+their names, use:
+.Bd -literal -offset indent
+Dwarf_Debug dbg;
+Dwarf_Signed ntypes;
+Dwarf_Type *types;
+Dwarf_Error err;
+int n, result;
+char *typename;
+
+/* Initialize dbg etc. */;
+result = dwarf_get_pubtypes(dbg, &types, &ntypes, &err);
+if (result != DW_DLV_OK) /* Handle the error. */
+	;
+
+/* Iterate over the returned array of descriptors. */
+for (n = 0; n < ntypes; n++) {
+	result = dwarf_pubtypename(types[n], &typename, &err);
+	if (result != DW_DLV_OK) /* Handle the error. */
+		;
+	printf("%s\en", typename);
+}
+
+/* Deallocate the returned array. */
+dwarf_types_dealloc(dbg, types, ntypes);
+.Ed
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Va cu_die_offset ,
+.Va cu_offset ,
+.Va dbg ,
+.Va die_offset ,
+.Va type ,
+.Va types ,
+.Va name ,
+or
+.Va ntypes
+was NULL.
+.It Bq Er DW_DLE_NO_ENTRY
+The DWARF debugging context referenced by argument
+.Ar dbg
+did not contain information about user-defined types.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_dealloc 3 ,
+.Xr dwarf_get_cu_die_offset_given_cu_header_offset 3 ,
+.Xr dwarf_pubtypes_dealloc 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_ranges.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,258 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_ranges.3 3182 2015-04-10 16:08:10Z emaste $
+.\"
+.Dd November 9, 2011
+.Os
+.Dt DWARF_GET_RANGES 3
+.Sh NAME
+.Nm dwarf_get_ranges
+.Nd retrieve non-contiguous address ranges
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_ranges
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Off offset"
+.Fa "Dwarf_Ranges **ranges"
+.Fa "Dwarf_Signed *cnt"
+.Fa "Dwarf_Unsigned *byte_cnt"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_get_ranges_a
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Off offset"
+.Fa "Dwarf_Die die"
+.Fa "Dwarf_Ranges **ranges"
+.Fa "Dwarf_Signed *cnt"
+.Fa "Dwarf_Unsigned *byte_cnt"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_ranges
+retrieves information about the non-contiguous address ranges associated
+with a DWARF debugging information entry.
+Information about address ranges is returned as an array of
+descriptors of type
+.Vt Dwarf_Ranges ,
+with each
+.Vt Dwarf_Ranges
+descriptor describing one address range entry.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF debug context allocated using
+.Xr dwarf_init 3 .
+.Pp
+Argument
+.Ar offset
+is an offset, relative to the
+.Dq ".debug_ranges"
+section, to the start of the desired list of address ranges.
+The offset of an address ranges list is indicated by the
+.Dv DW_AT_ranges
+attribute of a debugging information entry.
+.Pp
+Argument
+.Ar die
+(function
+.Fn dwarf_get_ranges_a
+only) is ignored in this implementation; see the section
+.Sx "Compatibility Notes"
+below.
+.Pp
+Argument
+.Ar ranges
+should point to a location that will be set to a pointer to an array
+of
+.Vt Dwarf_Ranges
+descriptors.
+.Pp
+Argument
+.Ar cnt
+should point to a location that will be set to the number of entries
+returned.
+If argument
+.Ar byte_cnt
+is not NULL, it will be set to the number of bytes occupied by the
+returned entries in the
+.Dq ".debug_ranges"
+section.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Pp
+.Vt Dwarf_Ranges
+descriptors are defined in the header file
+.In libdwarf.h ,
+and consists of the following fields:
+.Bl -tag -width ".Va dwr_addr1"
+.It Va dwr_addr1
+The first address offset, whose meaning depends on the type of the
+entry.
+.It Va dwr_addr2
+The second address offset, whose meaning depends on the type of the
+entry.
+.It Va dwr_type
+The type of this address range entry:
+.Bl -tag -width ".Dv DW_RANGES_ENTRY" -compact
+.It Dv DW_RANGES_ENTRY
+A range list entry.
+For this type of entry, the fields
+.Va dwr_addr1
+and
+.Va dwr_addr2
+hold the beginning and ending offsets of the address range, respectively.
+.It Dv DW_RANGES_ADDRESS_SELECTION
+A base address selection entry.
+For this type of entry, the field
+.Va dwr_addr1
+is the value of the largest representable address offset, and
+.Va dwr_addr2
+is a base address for the beginning and ending address offsets of
+subsequent address range entries in the list.
+.It Dv DW_RANGES_END
+An end of list mark.
+Both
+.Va dwr_addr1
+and
+.Va dwr_addr2
+are set to 0.
+.El
+.El
+.Ss Memory Management
+The memory area used for the array of
+.Vt Dwarf_Ranges
+descriptors returned in argument
+.Ar ranges
+is owned by the
+.Lb libdwarf .
+The application should not attempt to directly free this pointer.
+Portable code should instead use
+.Fn dwarf_ranges_dealloc
+to indicate that the memory may be freed.
+.Sh COMPATIBILITY
+Function
+.Fn dwarf_get_ranges_a
+is identical to
+.Fn dwarf_get_ranges ,
+except that it requires one additional argument
+.Ar die
+denoting the debugging information entry associated with
+the address range list.
+In this implementation of the
+.Lb libdwarf ,
+the argument
+.Ar die
+is ignored, and function
+.Fn dwarf_get_ranges_a
+is only provided for compatibility with other implementations of the
+DWARF(3) API.
+.Sh RETURN VALUES
+These functions
+return
+.Dv DW_DLV_OK
+when they succeed.
+They return
+.Dv DW_DLV_NO_ENTRY
+if there is no address range list at the specified offset
+.Ar offset .
+In case of an error, they return
+.Dv DW_DLV_ERROR
+and set the argument
+.Ar err .
+.Sh ERRORS
+These function can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_NO_ENTRY"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar dbg ,
+.Ar ranges
+or
+.Ar cnt
+was NULL.
+.It Bq Er DW_DLE_NO_ENTRY
+There is no address range list at the specified offset
+.Ar offset .
+.El
+.Sh EXAMPLE
+To retrieve the address range list associated with a debugging
+information entry, use:
+.Bd -literal -offset indent
+Dwarf_Debug dbg;
+Dwarf_Die die;
+Dwarf_Error de;
+Dwarf_Addr base;
+Dwarf_Attribute *attr_list;
+Dwarf_Ranges *ranges;
+Dwarf_Signed cnt;
+Dwarf_Unsigned off, attr_count, bytecnt;
+int i, j;
+
+if ((ret = dwarf_attrlist(die, &attr_list, &attr_count, &de)) !=
+    DW_DLV_OK)
+	errx(EXIT_FAILURE, "dwarf_attrlist failed: %s",
+	    dwarf_errmsg(de));
+
+for (i = 0; (Dwarf_Unsigned) i < attr_count; i++) {
+	if (dwarf_whatattr(attr_list[i], &attr, &de) != DW_DLV_OK) {
+		warnx("dwarf_whatattr failed: %s",
+		    dwarf_errmsg(de));
+		continue;
+	}
+	if (attr != DW_AT_ranges)
+		continue;
+	if (dwarf_formudata(attr_list[i], &off, &de) != DW_DLV_OK) {
+		warnx("dwarf_formudata failed: %s",
+		    dwarf_errmsg(de));
+		continue;
+	}
+	if (dwarf_get_ranges(dbg, (Dwarf_Off) off, &ranges, &cnt,
+	    &bytecnt, &de) != DW_DLV_OK)
+		continue;
+	for (j = 0; j < cnt; j++) {
+		if (ranges[j].dwr_type == DW_RANGES_END)
+			break;
+		else if (ranges[j].dwr_type ==
+		    DW_RANGES_ADDRESS_SELECTION)
+			base = ranges[j].dwr_addr2;
+		else {
+			/*
+			 * DW_RANGES_ENTRY entry.
+			 * .. Use dwr_addr1 and dwr_addr2 ..
+			 */
+		}
+	}
+}
+.Ed
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_ranges_dealloc 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_relocation_info.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,228 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_relocation_info.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd September 3, 2011
+.Os
+.Dt DWARF_GET_RELOCATION_INFO 3
+.Sh NAME
+.Nm dwarf_get_relocation_info
+.Nd retrieve generated relocation arrays
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_relocation_info
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_Signed *elf_section_index"
+.Fa "Dwarf_Signed *elf_section_link"
+.Fa "Dwarf_Unsigned *reloc_entry_count"
+.Fa "Dwarf_Relocation_Data *reloc_buf"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+The function
+.Fn dwarf_get_relocation_info
+is used to retrieve the relocation arrays generated by a prior call to
+.Xr dwarf_transform_to_disk_form 3 .
+.Pp
+Each call to this function retrieves the next available relocation
+array.
+Application code should call this function repeatly to retrieve all
+the relocation arrays.
+The total number of generated relocation arrays retrievable
+by this function may be obtained by calling function
+.Xr dwarf_get_relocation_info_count 3 .
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3 in sequence.
+or
+.Xr dwarf_producer_init_b 3 .
+The
+.Dv DW_DLC_SYMBOLIC_RELOCATIONS
+flag should have been set on the DWARF producer instance.
+.Pp
+Argument
+.Ar elf_section_index
+should point to a location which will be set to the ELF section index
+of the relocation section to which the retrieved relocation array
+belongs.
+.Pp
+Argument
+.Ar elf_section_link
+should point to a location which will be set to the section index of
+the ELF section to which the retrieved relocation array applies.
+.Pp
+Argument
+.Ar reloc_entry_count
+should point to a location which will be set to the total number of
+relocation entries contained in the relocation array.
+.Pp
+Argument
+.Ar reloc_buf
+should point to a location which will be set to a pointer to the
+retrieved array of relocation entries.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Pp
+The retrieved relocation entries are described using structure
+.Vt Dwarf_Relocation_Data_s ,
+defined in the header file
+.In libdwarf.h :
+.Bd -literal -offset indent
+typedef struct Dwarf_Relocation_Data_s {
+	unsigned char drd_type;
+	unsigned char drd_length;
+	Dwarf_Unsigned drd_offset;
+	Dwarf_Unsigned drd_symbol_index;
+} *Dwarf_Relocation_Data;
+.Ed
+.Pp
+Struct
+.Vt Dwarf_Relocation_Data_s
+consists of following fields:
+.Bl -tag -width ".Va drd_symbol_index" -compact -offset indent
+.It Va drd_type
+The type code of the relocation entry.
+The
+.Vt Dwarf_Rel_Type
+enumeration defined in the header file
+.In libdwarf.h
+specifies legal values for this field.
+.It Va drd_length
+The size in bytes of the field to be relocated.
+.It Va drd_offset
+The section-relative offset of the field to be relocated.
+.It Va drd_symbol_index
+The symbol index associated with the relocation entry.
+.El
+.Ss Memory Management
+The memory area used for the relocation arrays is managed by the
+.Lb libdwarf .
+The function
+.Fn dwarf_producer_finish
+may be used to release it, along with other resources associated
+with the producer instance.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_get_relocation_info
+returns
+.Dv DW_DLV_OK .
+It returns
+.Dv DW_DLV_NO_ENTRY
+if there were no more relocation arrays to retrieve, or if the flag
+.Dv DW_DLC_SYMBOLIC_RELOCATIONS
+was not set on the producer instance.
+In case of an error, function
+.Fn dwarf_get_relocation_info
+returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_relocation_info
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_NO_ENTRY"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar dbg ,
+.Ar elf_section_index ,
+.Ar elf_section_link ,
+.Ar reloc_entry_count
+or
+.Ar reloc_buf
+was NULL.
+.It Bq Er DW_DLE_NO_ENTRY
+There were no more ELF relocation arrays to retrieve.
+.It Bq Er DW_DLE_NO_ENTRY
+The flag
+.Dv DW_DLC_SYMBOLIC_RELOCATIONS
+was not set on the producer instance.
+.It Bq Er DW_DLE_NO_ENTRY
+Function
+.Xr dwarf_transform_to_disk_form 3
+was not called prior to calling function
+.Fn dwarf_get_relocation_info .
+.El
+.Sh EXAMPLES
+To generate relocation entries and retrieve them, use:
+.Bd -literal -offset indent
+Dwarf_P_Debug dbg;
+Dwarf_Relocation_Data buf;
+Dwarf_Signed count, index, link;
+Dwarf_Unsigned reloc_cnt, entry_cnt;
+Dwarf_Error de;
+int version, i, j;
+
+/*
+ * Assume that dbg refers to a DWARF producer instance created
+ * created with DW_DLC_SYMBOLIC_RELOCATIONS flag set and that
+ * application code has added DWARF debugging information
+ * to the producer instance.
+ */
+if ((count = dwarf_transform_to_disk_form(dbg, &de)) ==
+    DW_DLV_NOCOUNT) {
+	warnx("dwarf_transform_to_disk_form failed: %s",
+	    dwarf_errmsg(-1));
+	return;
+}
+
+/* ... process generated section byte streams ... */
+if (dwarf_get_relocation_info_count(dbg, &reloc_cnt, &version, &de) !=
+    DW_DLV_OK) {
+	warnx("dwarf_get_relocation_info_count failed: %s",
+	    dwarf_errmsg(-1));
+	return;
+}
+
+for (i = 0; (Dwarf_Unsigned) i < reloc_cnt; i++) {
+	if (dwarf_get_relocation_info(dbg, &index, &link, &entry_cnt,
+	    &buf, &de) != DW_DLV_OK) {
+		warnx("dwarf_get_relocation_info failed: %s",
+		    dwarf_errmsg(-1));
+		continue;
+	}
+	for (j = 0; (Dwarf_Unsigned) j < entry_cnt; j++) {
+		/* ...use each reloc data in buf[j]... */
+	}
+}
+
+dwarf_producer_finish(dbg, &de);
+.Ed
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_relocation_info_count 3 ,
+.Xr dwarf_reset_section_bytes 3 ,
+.Xr dwarf_producer_finish 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3 ,
+.Xr dwarf_transform_to_disk_form 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_relocation_info_count.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,116 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_relocation_info_count.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd September 3, 2011
+.Os
+.Dt DWARF_GET_RELOCATION_INFO_COUNT 3
+.Sh NAME
+.Nm dwarf_get_relocation_info_count
+.Nd return the number of relocation arrays
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_relocation_info_count
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_Unsigned *reloc_cnt"
+.Fa "int *drd_buffer_version"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_relocation_info_count
+retrieves the total number of relocation arrays generated by a prior
+call to
+.Xr dwarf_transform_to_disk_form 3 .
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+The
+.Dv DW_DLC_SYMBOLIC_RELOCATIONS
+flag should have been set on the producer instance.
+.Pp
+Argument
+.Ar reloc_cnt
+should point to a location which will be set to the total number of
+relocation arrays generated.
+.Pp
+Argument
+.Ar drd_buffer_version
+should point to a location which will be set to the version number
+of the relocation structures returned (see the symbol
+.Dv DWARF_DRD_BUFFER_VERSION ,
+defined in the header file
+.In libdwarf.h ) .
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_get_relocation_info_count
+returns
+.Dv DW_DLV_OK .
+It returns
+.Dv DW_DLV_NO_ENTRY
+if the
+.Dv DW_DLC_SYMBOLIC_RELOCATIONS
+flag is not set on the producer instance.
+In case of an error, function
+.Fn dwarf_get_relocation_info_count
+returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_relocation_info_count
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_NO_ENTRY"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar dbg ,
+.Ar reloc_cnt
+or
+.Ar drd_buffer_version
+was NULL.
+.It Bq Er DW_DLE_NO_ENTRY
+The
+.Dv DW_DLC_SYMBOLIC_RELOCATIONS
+flag was not set.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_relocation_info 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3 ,
+.Xr dwarf_transform_to_disk_form 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_section_bytes.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,157 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_section_bytes.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd August 26, 2011
+.Os
+.Dt DWARF_GET_SECTION_BYTES 3
+.Sh NAME
+.Nm dwarf_get_section_bytes
+.Nd retrieve ELF section byte streams
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft Dwarf_Ptr
+.Fo dwarf_get_section_bytes
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_Signed dwarf_section"
+.Fa "Dwarf_Signed *elf_section_index"
+.Fa "Dwarf_Unsigned *length"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_section_bytes
+returns the ELF section byte streams generated by a prior call
+to function
+.Xr dwarf_transform_to_disk_form 3 .
+.Pp
+Each call to function
+.Fn dwarf_get_section_bytes
+will return the byte stream for one ELF section.
+The first call to this function will always return the first ELF
+section, and the subsequent calls will return the rest of sections
+in the order when they were generated, until the last one.
+The total number of sections generated is returned by the function
+.Xr dwarf_transform_to_disk_form 3 .
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using the
+functions
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar dwarf_section
+is currently ignored.
+.Pp
+Argument
+.Ar elf_section_index
+should point to a location which will be set to the section index value
+of the returned ELF section.
+.Pp
+Argument
+.Ar length
+should point to a location which will hold the length in bytes of the
+returned ELF section.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Ss Memory Management
+The memory areas used for the returned ELF section byte streams should
+be freed using the function
+.Fn dwarf_producer_finish .
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_get_section_bytes
+returns a pointer to a ELF section byte stream.
+In case of an error, function
+.Fn dwarf_get_section_bytes
+will return NULL and set the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_section_bytes
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_NO_ENTRY"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar dbg ,
+.Ar elf_section_index ,
+or
+.Ar length
+was NULL.
+.It Bq Er DW_DLE_NO_ENTRY
+There were no more ELF sections to retrieve, or the function was
+called before a call to
+.Xr dwarf_transform_to_disk_form 3 .
+.El
+.Sh EXAMPLES
+To generate and retrieve ELF section byte streams, use:
+.Bd -literal -offset indent
+Dwarf_P_Debug dbg;
+Dwarf_Signed count, i, sec_index;
+Dwarf_Unsigned len;
+Dwarf_Ptr bytes;
+Dwarf_Error de;
+
+/* ... Assume that `dbg' refers to a DWARF producer instance,
+ * and that application code has added DWARF debugging
+ * information to the producer instance. ...
+ */
+if ((count = dwarf_transform_to_disk_form(dbg, &de)) ==
+    DW_DLV_NOCOUNT) {
+	warnx("dwarf_transform_to_disk_form failed: %s",
+	    dwarf_errmsg(-1));
+	return;
+}
+
+/* Retrieve section data. */
+for (i = 0; i < count; i++) {
+	bytes = dwarf_get_section_bytes(dbg, i, &sec_index, &len,
+	    &de);
+	if (bytes == NULL) {
+		warnx("dwarf_get_section_bytes failed: %s",
+		    dwarf_errmsg(-1));
+		continue;
+	}
+	/* ... use the returned byte stream ... */
+}
+
+/* Release resources. */
+dwarf_producer_finish(dbg, &de);
+.Ed
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_reset_section_bytes 3 ,
+.Xr dwarf_producer_finish 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3 ,
+.Xr dwarf_transform_to_disk_form 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_section_max_offsets.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,116 @@
+.\" Copyright (c) 2014 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_section_max_offsets.3 3141 2015-01-29 23:11:10Z jkoshy $
+.\"
+.Dd December 21, 2014
+.Os
+.Dt DWARF_GET_SECTION_MAX_OFFSETS
+.Sh NAME
+.Nm dwarf_get_section_max_offsets ,
+.Nm dwarf_get_section_max_offsets_b
+.Nd return the size of DWARF sections
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_section_max_offsets
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Unsigned *debug_info"
+.Fa "Dwarf_Unsigned *debug_abbrev"
+.Fa "Dwarf_Unsigned *debug_line"
+.Fa "Dwarf_Unsigned *debug_loc"
+.Fa "Dwarf_Unsigned *debug_aranges"
+.Fa "Dwarf_Unsigned *debug_macinfo"
+.Fa "Dwarf_Unsigned *debug_pubnames"
+.Fa "Dwarf_Unsigned *debug_str"
+.Fa "Dwarf_Unsigned *debug_frame"
+.Fa "Dwarf_Unsigned *debug_ranges"
+.Fa "Dwarf_Unsigned *debug_pubtypes"
+.Fc
+.Ft int
+.Fo dwarf_get_section_max_offsets_b
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Unsigned *debug_info"
+.Fa "Dwarf_Unsigned *debug_abbrev"
+.Fa "Dwarf_Unsigned *debug_line"
+.Fa "Dwarf_Unsigned *debug_loc"
+.Fa "Dwarf_Unsigned *debug_aranges"
+.Fa "Dwarf_Unsigned *debug_macinfo"
+.Fa "Dwarf_Unsigned *debug_pubnames"
+.Fa "Dwarf_Unsigned *debug_str"
+.Fa "Dwarf_Unsigned *debug_frame"
+.Fa "Dwarf_Unsigned *debug_ranges"
+.Fa "Dwarf_Unsigned *debug_pubtypes"
+.Fa "Dwarf_Unsigned *debug_types"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_section_max_offsets_b
+retrieves the sizes of the DWARF sections in a DWARF debug context.
+Argument
+.Ar dbg
+should reference a DWARF debug context allocated using
+.Xr dwarf_init 3 .
+The function stores the size of each DWARF section to the location
+pointed to by the argument corresponding to the section name.
+If a DWARF section does not exist, the location pointed to by the
+argument corresponding to that section will be set to zero.
+.Pp
+A value of NULL may be used for any of the arguments
+.Ar debug_info ,
+.Ar debug_abbrev ,
+.Ar debug_line ,
+.Ar debug_loc ,
+.Ar debug_aranges ,
+.Ar debug_macinfo ,
+.Ar debug_pubnames ,
+.Ar debug_str ,
+.Ar debug_frame ,
+.Ar debug_ranges ,
+.Ar debug_pubtypes
+and
+.Ar debug_types
+if the caller is not interested in the respective section size.
+.Pp
+Function
+.Fn dwarf_get_section_max_offsets
+is identical to function
+.Fn dwarf_get_section_max_offsets_b
+except that it does not provide argument
+.Ar debug_types ,
+and thus cannot return the size of the
+.Dq \&.debug_types
+section.
+.Sh RETURN VALUES
+On success, these functions return
+.Dv DW_DLV_OK .
+If argument
+.Ar dbg
+is NULL, they return
+.Dv DW_DLV_ERROR .
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_init 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_str.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,149 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_str.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd April 3, 2011
+.Os
+.Dt DWARF_GET_STR 3
+.Sh NAME
+.Nm dwarf_get_str
+.Nd retrieve a string from the DWARF string section
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_str
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Off offset"
+.Fa "char **string"
+.Fa "Dwarf_Signed *len"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_get_str
+retrieves a NUL-terminated string from the DWARF string section
+.Dq ".debug_str" .
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF debug context allocated using
+.Xr dwarf_init 3 .
+.Pp
+Argument
+.Ar offset
+should be an offset, relative to the
+.Dq ".debug_str"
+section, specifying the start of the desired string.
+.Pp
+Argument
+.Ar string
+should point to a location which will hold a returned
+pointer to a NUL-terminated string.
+.Pp
+Argument
+.Ar len
+should point to a location which will hold the length
+of the returned string.
+The returned length does not include the space needed for
+the NUL-terminator.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_get_str
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+It returns
+.Dv DW_DLV_NO_ENTRY
+if there is no
+.Dq ".debug_str"
+section associated with the specified debugging context,
+or if the provided offset
+.Ar offset
+is at the very end of
+.Dq ".debug_str"
+section.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_get_str
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_NO_ENTRY"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar dbg ,
+.Ar string
+or
+.Ar len
+was NULL.
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Ar offset
+was out of range.
+.It Bq Er DW_DLE_NO_ENTRY
+The debugging context
+.Ar dbg
+did not contain a
+.Dq ".debug_str"
+string section.
+.It Bq Er DW_DLE_NO_ENTRY
+Argument
+.Ar offset
+was at the very end of the
+.Dq ".debug_str"
+section.
+.El
+.Sh EXAMPLE
+To retrieve all the strings in the DWARF string section, use:
+.Bd -literal -offset indent
+Dwarf_Debug dbg;
+Dwarf_Off offset;
+Dwarf_Signed len;
+Dwarf_Error de;
+char *str;
+int ret
+
+offset = 0;
+while ((ret = dwarf_get_str(dbg, offset, &str, &len, &de)) ==
+	DW_DLV_OK) {
+	/* .. Use the retrieved string. .. */
+	offset += len + 1; /* Account for the terminating NUL. */
+}
+
+if (ret == DW_DLV_ERROR)
+	warnx("dwarf_get_str: %s", dwarf_errmsg(de));
+.Ed
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_init 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_types.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,232 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_types.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd April 10, 2011
+.Os
+.Dt DWARF_GET_TYPES 3
+.Sh NAME
+.Nm dwarf_get_types ,
+.Nm dwarf_type_cu_offset ,
+.Nm dwarf_type_die_offset ,
+.Nm dwarf_type_name_offsets ,
+.Nm dwarf_typename
+.Nd retrieve information about user-defined types
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_types
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Type **types"
+.Fa "Dwarf_Signed *ntypes"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_type_cu_offset
+.Fa "Dwarf_Type type"
+.Fa "Dwarf_Off *cu_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_type_die_offset
+.Fa "Dwarf_Type type"
+.Fa "Dwarf_Off *die_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_type_name_offsets
+.Fa "Dwarf_Type type"
+.Fa "char **name"
+.Fa "Dwarf_Off *die_offset"
+.Fa "Dwarf_Off *cu_die_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_typename
+.Fa "Dwarf_Type type"
+.Fa "char **name"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+These APIs retrieve information about user-defined types from the
+SGI-specific
+.Dq ".debug_typenames"
+section.
+.Pp
+Standards-conformant applications should use the functions
+.Xr dwarf_get_pubtypes 3 ,
+.Xr dwarf_pubtype_cu_offset 3 ,
+.Xr dwarf_pubtype_die_offset 3 ,
+.Xr dwarf_pubtype_name_offsets 3
+and
+.Xr dwarf_pubtypename 3 ,
+which operate on the equivalent
+.Dq ".debug_pubtypes"
+section defined by the DWARF3 standard.
+.Pp
+Information about user-defined types is returned using opaque descriptors
+of type
+.Vt Dwarf_Type .
+Applications need to use the functions described below to retrieve
+the name and offset information contained in these descriptors.
+.Pp
+Function
+.Fn dwarf_get_types
+retrieves descriptors for all user-defined types associated with the
+DWARF debug context specified by argument
+.Ar dbg .
+The argument
+.Ar types
+should point to a location that will be set to a pointer to an array
+of
+.Vt Dwarf_Type
+descriptors.
+The argument
+.Ar ntypes
+should point to a location that will be set to the number of
+descriptors returned.
+.Pp
+Function
+.Fn dwarf_type_cu_offset
+returns the offset, relative to the
+.Dq ".debug_info"
+section, of the compilation unit that contains the debugging
+information entry associated with the argument
+.Ar type .
+Argument
+.Ar cu_offset
+should point to a location that will hold the returned offset.
+.Pp
+Function
+.Fn dwarf_type_die_offset
+retrieves the offset, relative to the
+.Dq ".debug_info"
+section, of the debugging information entry associated with the
+argument
+.Ar type ,
+and stores it into the location pointed to by the argument
+.Ar die_offset .
+.Pp
+Function
+.Fn dwarf_type_name_offsets
+retrieves the name and offsets for the debugging information
+entry for argument
+.Ar type .
+Argument
+.Ar name
+should point to a location which will be set to a pointer to a
+NUL-terminated string containing the name of the associated debugging
+information entry.
+Argument
+.Ar die_offset
+should point to a location which will be set to the offset, relative
+to the
+.Dq ".debug_info"
+section, of the associated debugging information entry.
+Argument
+.Ar cu_die_offset
+should point to a location which will be set to a offset, relative to
+the
+.Dq ".debug_info"
+section, of the first debugging information entry in the compilation
+unit associated with argument
+.Ar type .
+.Pp
+Function
+.Fn dwarf_typename
+sets the location pointed to by argument
+.Ar name
+to a pointer to a NUL-terminated string holding the name of the
+debugging information entry associated with the argument
+.Ar type .
+.Ss Memory Management
+The memory area used for the array of
+.Vt Dwarf_Type
+descriptors returned in argument
+.Ar types
+by function
+.Fn dwarf_get_types
+is owned by the
+.Lb libdwarf .
+Application code should not attempt to directly free this pointer.
+Portable code should instead use the function
+.Xr dwarf_types_dealloc 3
+to indicate that the memory area may be freed.
+.Pp
+The memory area used for the string returned in the
+.Ar name
+argument to functions
+.Fn dwarf_type_name_offsets
+and
+.Fn dwarf_typename
+is owned by the
+.Lb libdwarf .
+Portable code should indicate that the memory area can
+be freed using the
+.Xr dwarf_dealloc 3
+function.
+.Ss Error Returns
+If argument
+.Ar err
+is not NULL, these functions will use it to store error information,
+in case of an error.
+.Sh RETURN VALUES
+On success, these functions returns
+.Dv DW_DLV_OK .
+In case of an error, they return
+.Dv DW_DLV_ERROR
+and set the argument
+.Ar err .
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Va cu_die_offset ,
+.Va cu_offset ,
+.Va dbg ,
+.Va die_offset ,
+.Va type ,
+.Va types ,
+.Va name ,
+or
+.Va ntypes
+was NULL.
+.It Bq Er DW_DLE_NO_ENTRY
+The DWARF debugging context referenced by argument
+.Ar dbg
+did not contain information about user-defined types.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_cu_die_offset_given_cu_header_offset 3 ,
+.Xr dwarf_get_pubtypes 3 ,
+.Xr dwarf_pubtype_cu_offset 3 ,
+.Xr dwarf_pubtype_die_offset 3 ,
+.Xr dwarf_pubtype_name_offsets 3 ,
+.Xr dwarf_pubtypename 3 ,
+.Xr dwarf_types_dealloc 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_vars.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,210 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_vars.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd April 2, 2011
+.Os
+.Dt DWARF_GET_VARS 3
+.Sh NAME
+.Nm dwarf_get_vars ,
+.Nm dwarf_var_cu_offset ,
+.Nm dwarf_var_die_offset ,
+.Nm dwarf_var_name_offsets ,
+.Nm dwarf_varname
+.Nd retrieve information about static variables
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_vars
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Var **vars"
+.Fa "Dwarf_Signed *nvars"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_var_cu_offset
+.Fa "Dwarf_Var var"
+.Fa "Dwarf_Off *cu_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_var_die_offset
+.Fa "Dwarf_Var var"
+.Fa "Dwarf_Off *die_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_var_name_offsets
+.Fa "Dwarf_Var var"
+.Fa "char **name"
+.Fa "Dwarf_Off *die_offset"
+.Fa "Dwarf_Off *cu_die_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_varname
+.Fa "Dwarf_Var var"
+.Fa "char **name"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+These functions retrieve information about the file scope static
+variables associated with a DWARF debug context.
+Information about these static variables is returned using opaque
+descriptors of type
+.Vt Dwarf_Var .
+Applications need to use the functions described below to retrieve
+the name and offset information contained in these descriptors.
+.Pp
+Function
+.Fn dwarf_get_vars
+retrieves descriptors for all the static variables associated with the
+DWARF debug context specified by argument
+.Ar dbg .
+The argument
+.Ar vars
+should point to a location that will be set to a pointer to an array
+of
+.Vt Dwarf_Var
+descriptors.
+The argument
+.Ar nvars
+should point to a location that will be set to the number of
+descriptors returned.
+.Pp
+Function
+.Fn dwarf_var_cu_offset
+returns the section-relative offset, relative to the
+.Dq ".debug_info"
+section, of the compilation unit that
+contains the debugging information entry associated with the argument
+.Ar var .
+Argument
+.Ar cu_offset
+should point to a location that will hold the returned offset.
+.Pp
+Function
+.Fn dwarf_var_die_offset
+retrieves the section-relative offset, relative to the
+.Dq ".debug_info"
+section, of the debugging information
+entry associated with the argument
+.Ar var ,
+and stores it into the location pointed to by the argument
+.Ar die_offset .
+.Pp
+Function
+.Fn dwarf_var_name_offsets
+retrieves both the name and the associated offsets for the debugging
+information entry for argument
+.Ar var .
+Argument
+.Ar name
+should point to a location which will be set to a pointer to a
+NUL-terminated string containing the name of the associated debugging
+information entry.
+Argument
+.Ar die_offset
+should point to a location which will be set to a section-relative
+offset, relative to the
+.Dq ".debug_info"
+section, of the associated debugging information entry.
+Argument
+.Ar cu_die_offset
+should point to a location which will be set to a
+section-relative offset, relative to the
+.Dq ".debug_info"
+section, of the first debugging information entry in
+the compilation unit associated with argument
+.Ar var .
+.Pp
+Function
+.Fn dwarf_varname
+sets the location pointed to by argument
+.Ar name
+to a pointer to a NUL-terminated string holding the name of the
+debugging information entry associated with the argument
+.Ar var .
+.Ss Memory Management
+The memory area used for the array of
+.Vt Dwarf_Var
+descriptors returned in argument
+.Ar vars
+by function
+.Fn dwarf_get_vars
+is owned by the
+.Lb libdwarf .
+Application code should not attempt to directly free this pointer.
+Portable code should instead use the function
+.Xr dwarf_vars_dealloc 3
+to indicate that the memory area may be freed.
+.Pp
+The memory area used for the string returned in the
+.Ar name
+argument to functions
+.Fn dwarf_var_name_offsets
+and
+.Fn dwarf_varname
+is owned by the
+.Lb libdwarf .
+Portable code should indicate that the memory area can
+be freed using the
+.Xr dwarf_dealloc 3
+function.
+.Ss Error Returns
+If argument
+.Ar err
+is not NULL, these functions will use it to store error information,
+in case of an error.
+.Sh RETURN VALUES
+On success, these functions returns
+.Dv DW_DLV_OK .
+In case of an error, they return
+.Dv DW_DLV_ERROR
+and set the argument
+.Ar err .
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Va cu_die_offset ,
+.Va cu_offset ,
+.Va dbg ,
+.Va die_offset ,
+.Va var ,
+.Va vars ,
+.Va name ,
+or
+.Va nvars
+was NULL.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_dealloc 3 ,
+.Xr dwarf_get_cu_die_offset_given_cu_header_offset 3 ,
+.Xr dwarf_vars_dealloc 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_get_weaks.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,215 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_get_weaks.3 2071 2011-10-27 03:20:00Z jkoshy $
+.\"
+.Dd April 10, 2011
+.Os
+.Dt DWARF_GET_WEAKS 3
+.Sh NAME
+.Nm dwarf_get_weaks ,
+.Nm dwarf_weak_cu_offset ,
+.Nm dwarf_weak_die_offset ,
+.Nm dwarf_weak_name_offsets ,
+.Nm dwarf_weakname
+.Nd retrieve information about weak symbols
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_get_weaks
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Weak **weaks"
+.Fa "Dwarf_Signed *nweaks"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_weak_cu_offset
+.Fa "Dwarf_Weak weak"
+.Fa "Dwarf_Off *cu_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_weak_die_offset
+.Fa "Dwarf_Weak weak"
+.Fa "Dwarf_Off *die_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_weak_name_offsets
+.Fa "Dwarf_Weak weak"
+.Fa "char **name"
+.Fa "Dwarf_Off *die_offset"
+.Fa "Dwarf_Off *cu_die_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_weakname
+.Fa "Dwarf_Weak weak"
+.Fa "char **name"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+These functions retrieve information about weak symbols from the
+lookup tables in the (SGI-specific)
+.Dq ".debug_weaknames"
+section.
+Information about weak symbols is returned using opaque descriptors
+of type
+.Vt Dwarf_Weak .
+Applications need to use the functions described below to retrieve
+the name and offset information contained in these descriptors.
+.Pp
+Function
+.Fn dwarf_get_weaks
+retrieves descriptors for all the weak symbols associated with the
+DWARF debug context specified by argument
+.Ar dbg .
+The argument
+.Ar weaks
+should point to a location that will be set to a pointer to an array
+of
+.Vt Dwarf_Weak
+descriptors.
+The argument
+.Ar nweaks
+should point to a location that will be set to the number of
+descriptors returned.
+.Pp
+Function
+.Fn dwarf_weak_cu_offset
+returns the offset, relative to the
+.Dq ".debug_info"
+section, of the compilation unit that contains the debugging
+information entry associated with the argument
+.Ar weak .
+Argument
+.Ar cu_offset
+should point to a location that will hold the returned offset.
+.Pp
+Function
+.Fn dwarf_weak_die_offset
+retrieves the offset, relative to the
+.Dq ".debug_info"
+section, of the debugging information entry associated with the
+argument
+.Ar weak ,
+and stores it into the location pointed to by the argument
+.Ar die_offset .
+.Pp
+Function
+.Fn dwarf_weak_name_offsets
+retrieves the name and offsets for the debugging information
+entry for argument
+.Ar weak .
+Argument
+.Ar name
+should point to a location which will be set to a pointer to a
+NUL-terminated string containing the name of the associated debugging
+information entry.
+Argument
+.Ar die_offset
+should point to a location which will be set to the offset, relative
+to the
+.Dq ".debug_info"
+section, of the associated debugging information entry.
+Argument
+.Ar cu_die_offset
+should point to a location which will be set to the
+offset, relative to the
+.Dq ".debug_info"
+section, of the first debugging information entry in the compilation
+unit associated with argument
+.Ar weak .
+.Pp
+Function
+.Fn dwarf_weakname
+sets the location pointed to by argument
+.Ar name
+to a pointer to a NUL-terminated string holding the name of the
+debugging information entry associated with the argument
+.Ar weak .
+.Ss Memory Management
+The memory area used for the array of
+.Vt Dwarf_Weak
+descriptors returned in argument
+.Ar weaks
+by function
+.Fn dwarf_get_weaks
+is owned by the
+.Lb libdwarf .
+Application code should not attempt to directly free this pointer.
+Portable code should instead use the function
+.Xr dwarf_weaks_dealloc 3
+to indicate that the memory area may be freed.
+.Pp
+The memory area used for the string returned in the
+.Ar name
+argument to functions
+.Fn dwarf_weak_name_offsets
+and
+.Fn dwarf_weakname
+is owned by the
+.Lb libdwarf .
+Portable code should indicate that the memory area can
+be freed using the
+.Xr dwarf_dealloc 3
+function.
+.Ss Error Returns
+If argument
+.Ar err
+is not NULL, these functions will use it to store error information,
+in case of an error.
+.Sh RETURN VALUES
+On success, these functions returns
+.Dv DW_DLV_OK .
+In case of an error, they return
+.Dv DW_DLV_ERROR
+and set the argument
+.Ar err .
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Va cu_die_offset ,
+.Va cu_offset ,
+.Va dbg ,
+.Va die_offset ,
+.Va weak ,
+.Va weaks ,
+.Va name ,
+or
+.Va nweaks
+was NULL.
+.It Bq Er DW_DLE_NO_ENTRY
+The DWARF debugging context referenced by argument
+.Ar dbg
+did not contain information about weak symbols.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_cu_die_offset_given_cu_header_offset 3 ,
+.Xr dwarf_weaks_dealloc 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_hasattr.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,92 @@
+.\" Copyright (c) 2010 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_hasattr.3 3181 2015-04-10 13:22:51Z emaste $
+.\"
+.Dd April 17, 2010
+.Os
+.Dt DWARF_HASATTR 3
+.Sh NAME
+.Nm dwarf_hasattr
+.Nd check for the presence of an attribute
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_hasattr
+.Fa "Dwarf_Die die"
+.Fa "Dwarf_Half attr"
+.Fa "Dwarf_Bool *ret_bool"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_hasattr
+tests whether the debugging information entry referenced in argument
+.Ar die
+contains the attribute named by argument
+.Ar attr .
+Legal values for argument
+.Ar attr
+are those denoted by the
+.Dv DW_AT_*
+constants in the DWARF specification.
+.Pp
+If the named attribute is present in the debugging information entry,
+function
+.Fn dwarf_hasattr
+returns a non-zero value in the location pointed to by argument
+.Ar ret_bool .
+If the named attribute is not present, a zero is written instead.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to return an error descriptor in case
+of an error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_hasattr
+returns
+.Dv DW_DLV_OK .
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_hasattr
+can fail with the following error:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Either of argument
+.Va die
+or
+.Va ret_bool
+was NULL.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_attr 3 ,
+.Xr dwarf_whatattr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_hasform.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,127 @@
+.\" Copyright (c) 2010 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: dwarf_hasform.3 2073 2011-10-27 03:30:47Z jkoshy $
+.\"
+.Dd May 22, 2010
+.Os
+.Dt DWARF_HASFORM 3
+.Sh NAME
+.Nm dwarf_hasform ,
+.Nm dwarf_whatform ,
+.Nm dwarf_whatform_direct
+.Nd query attribute forms
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_hasform
+.Fa "Dwarf_Attribute attr"
+.Fa "Dwarf_Half form"
+.Fa "Dwarf_Bool *ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_whatform
+.Fa "Dwarf_Attribute attr"
+.Fa "Dwarf_Half *retform"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_whatform_direct
+.Fa "Dwarf_Attribute attr"
+.Fa "Dwarf_Half *retform"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_hasform
+indicates whether the DWARF attribute denoted by argument
+.Ar attr
+has the attribute form specified by argument
+.Ar form .
+If the attribute has the specified form, then
+argument
+.Ar ret
+is set to a non-zero value, otherwise it is set to zero.
+If argument
+.Ar err
+is non-NULL, it will be used to return an error descriptor in
+case of an error.
+.Pp
+Function
+.Fn dwarf_whatform
+sets the location specified by argument
+.Ar retform
+to the attribute form code for the DWARF attribute referenced
+by argument
+.Ar attr .
+If the attribute referenced by argument
+.Ar attr
+has an indirect form attribute, this function will return the final
+form for the attribute.
+If argument
+.Ar err
+is non-NULL, it will be used to return an error descriptor in
+case of an error.
+.Pp
+Function
+.Fn dwarf_whatform_direct
+sets the location specified by argument
+.Ar retform
+to the attribute form code for the DWARF attribute referenced
+by argument
+.Ar attr .
+If the form is an indirect form, the function sets the location
+specified by argument
+.Ar retform
+to
+.Dv DW_FORM_indirect .
+If argument
+.Ar err
+is non-NULL, it will be used to return an error descriptor in
+case of an error.
+.Sh RETURN VALUES
+These functions return
+.Dv DW_DLV_OK
+on success.
+In case of an error, these functions return
+.Dv DW_DLV_ERR
+and set argument
+.Ar err .
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Any of the arguments
+.Ar attr ,
+.Ar ret ,
+or
+.Ar retform
+was NULL.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_attr 3 ,
+.Xr dwarf_hasattr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_highpc.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,193 @@
+.\" Copyright (c) 2010,2014 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_highpc.3 3092 2014-09-02 22:09:30Z kaiwang27 $
+.\"
+.Dd July 22, 2014
+.Os
+.Dt DWARF_HIGHPC 3
+.Sh NAME
+.Nm dwarf_arrayorder ,
+.Nm dwarf_bitoffset ,
+.Nm dwarf_bitsize ,
+.Nm dwarf_bytesize ,
+.Nm dwarf_highpc ,
+.Nm dwarf_highpc_b ,
+.Nm dwarf_lowpc ,
+.Nm dwarf_srclang
+.Nd retrieve the value of a DWARF attribute
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_arrayorder
+.Fa "Dwarf_Die die"
+.Fa "Dwarf_Unsigned *ret_order"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_bitoffset
+.Fa "Dwarf_Die die"
+.Fa "Dwarf_Unsigned *ret_size"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_bitsize
+.Fa "Dwarf_Die die"
+.Fa "Dwarf_Unsigned *ret_size"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_bytesize
+.Fa "Dwarf_Die die"
+.Fa "Dwarf_Unsigned *ret_size"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_highpc
+.Fa "Dwarf_Die die"
+.Fa "Dwarf_Addr *ret_highpc"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_highpc_b
+.Fa "Dwarf_Die die"
+.Fa "Dwarf_Addr *ret_highpc"
+.Fa "Dwarf_Half *ret_form"
+.Fa "enum Dwarf_Form_Class *ret_class"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_lowpc
+.Fa "Dwarf_Die die"
+.Fa "Dwarf_Addr *ret_lowpc"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_srclang
+.Fa "Dwarf_Die die"
+.Fa "Dwarf_Unsigned *ret_lang"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+These convenience functions are used to retrieve DWARF attribute
+values associated with a Debugging Information Entry (DIE) descriptor
+denoted by argument
+.Ar die .
+These functions store the value of the requested attribute into the
+location pointed to by their second argument, provided that the requested
+attribute exists in the debugging information entry.
+.Pp
+The list of functions and the DWARF attribute that they retrieve are:
+.Pp
+.Bl -tag -width ".Fn dwarf_arrayorder" -compact
+.It Fn dwarf_arrayorder
+Retrieve the
+.Dv DW_AT_ordering
+attribute value.
+.It Fn dwarf_bitoffset
+Retrieve the
+.Dv DW_AT_bit_offset
+attribute value.
+.It Fn dwarf_bitsize
+Retrieve the
+.Dv DW_AT_bit_size
+attribute value.
+.It Fn dwarf_bytesize
+Retrieve the
+.Dv DW_AT_byte_size
+attribute value.
+.It Fn dwarf_highpc
+Retrieve the
+.Dv DW_AT_high_pc
+attribute value.
+.It Fn dwarf_highpc_b
+Retrieve the
+.Dv DW_AT_high_pc
+attribute value.
+.It Fn dwarf_lowpc
+Retrieve the
+.Dv DW_AT_low_pc
+attribute value.
+.It Fn dwarf_srclang
+Retrieve the
+.Dv DW_AT_language
+attribute value.
+.El
+.Pp
+Function
+.Fn dwarf_highpc_b
+is an enhanced version of function
+.Fn dwarf_highpc .
+It sets the location specified by argument
+.Ar ret_form
+to the form code of the attribute
+.Dv DW_AT_high_pc ,
+and sets the location specified by argument
+.Ar ret_class
+to the class of that form.
+A value of NULL may be used for either of the arguments
+.Ar ret_form
+or
+.Ar ret_class
+if the caller is not interested in the respective value.
+.Sh RETURN VALUES
+These functions return
+.Dv DW_DLV_OK on success.
+.Pp
+If the debugging information entry descriptor denoted by argument
+.Ar die
+does not contain the requested attribute, these functions return
+.Dv DW_DLV_NO_ENTRY
+and set argument
+.Ar err .
+For other errors, they return
+.Dv DW_DLV_ERROR
+and set argument
+.Ar err .
+.Sh ERRORS
+These functions can fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Arguments
+.Ar die ,
+.Ar ret_highpc ,
+.Ar ret_lowpc ,
+.Ar ret_size ,
+.Ar ret_lang
+or
+.Ar ret_order
+were NULL.
+.It Bq Er DW_DLE_NO_ENTRY
+Argument
+.Ar die
+had no requested attribute.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_attr 3 ,
+.Xr dwarf_attrlist 3 ,
+.Xr dwarf_hasattr 3 ,
+.Xr dwarf_get_form_class 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_init.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,178 @@
+.\" Copyright (c) 2009 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: dwarf_init.3 2122 2011-11-09 15:35:14Z jkoshy $
+.\"
+.Dd November 9, 2011
+.Os
+.Dt DWARF_INIT 3
+.Sh NAME
+.Nm dwarf_init ,
+.Nm dwarf_elf_init
+.Nd allocate a DWARF debug descriptor
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_init
+.Fa "int fd"
+.Fa "int mode"
+.Fa "Dwarf_Handler errhand"
+.Fa "Dwarf_Ptr errarg"
+.Fa "Dwarf_Debug *ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft in
+.Fo dwarf_elf_init
+.Fa "Elf *elf"
+.Fa "int mode"
+.Fa "Dwarf_Handler errhand"
+.Fa "Dwarf_Ptr errarg"
+.Fa "Dwarf_Debug *ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+These functions allocate and return a
+.Vt Dwarf_Debug
+instance for the object denoted by argument
+.Ar fd
+or
+.Ar elf .
+This instance would be used for subsequent access to debugging information in the object by other functions in the DWARF(3) library.
+.Pp
+For function
+.Fn dwarf_init ,
+argument
+.Ar fd
+denotes an open file descriptor referencing a compilation object.
+Function
+.Fn dwarf_init
+implicitly allocates an
+.Vt Elf
+descriptor for argument
+.Ar fd .
+.Pp
+For function
+.Fn dwarf_elf_init ,
+argument
+.Ar elf
+denotes a descriptor returned by
+.Xr elf_begin 3
+or
+.Xr elf_memory 3 .
+.Pp
+Argument
+.Ar mode
+specifies the access mode desired.
+It should be at least as permissive as the mode with which
+the file descriptor
+.Ar fd
+or the ELF descriptor
+.Ar elf
+was created with.
+Legal values for argument
+.Ar mode
+are:
+.Pp
+.Bl -tag -width "DW_DLC_WRITE" -compact
+.It DW_DLC_RDWR
+Permit reading and writing of DWARF information.
+.It DW_DLC_READ
+Operate in read-only mode.
+.It DW_DLC_WRITE
+Permit writing of DWARF information.
+.El
+.Pp
+Argument
+.Ar errhand
+denotes a function to be called in case of an error.
+If this argument is
+.Dv NULL
+then a default error handling scheme is used.
+See
+.Xr dwarf 3
+for a description of the error handling scheme used by the
+DWARF(3) library.
+.Pp
+Argument
+.Ar errarg
+is passed to the error handler function denoted by argument
+.Ar errhand
+when it is invoked.
+.Pp
+Argument
+.Ar ret
+points to the memory location that will hold a
+.Vt Dwarf_Debug
+reference on a successful call these functions.
+.Pp
+Argument
+.Ar err
+references a memory location that would hold a
+.Vt Dwarf_Error
+descriptor in case of an error.
+.Ss Memory Management
+The
+.Vt Dwarf_Debug
+instance returned by these functions should be freed using
+.Fn dwarf_finish .
+.Sh RETURN VALUES
+These functions return the following values:
+.Bl -tag -width ".Bq Er DW_DLV_NO_ENTRY"
+.It Bq Er DW_DLV_OK
+This return value indicates a successful return.
+.It Bq Er DW_DLV_ERROR
+The operation failed.
+.It Bq Er DW_DLV_NO_ENTRY
+The object specified by arguments
+.Ar "fd"
+or
+.Ar "elf"
+did not contain debug information.
+.El
+.Sh IMPLEMENTATION NOTES
+The current implementation does not support access modes
+.Dv DW_DLC_RDWR
+and
+.Dv DW_DLC_WRITE .
+.Sh EXAMPLES
+To initialize a
+.Vt Dwarf_Debug
+instance from a open file descriptor referencing an ELF object, and
+with the default error handler, use:
+.Bd -literal -offset indent
+Dwarf_Error err;
+Dwarf_Debug dbg;
+
+if (dwarf_init(fd, DW_DLC_READ, NULL, NULL, &dbg, &err) !=
+    DW_DLV_OK)
+	errx(EXIT_FAILURE, "dwarf_init: %s", dwarf_errmsg(err));
+.Ed
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_errmsg 3 ,
+.Xr dwarf_finish 3 ,
+.Xr dwarf_get_elf 3 ,
+.Xr elf_begin 3 ,
+.Xr elf_memory 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_init.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,163 @@
+/*-
+ * Copyright (c) 2007 John Birrell (jb@freebsd.org)
+ * Copyright (c) 2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_init.c 2073 2011-10-27 03:30:47Z jkoshy $");
+
+int
+dwarf_elf_init(Elf *elf, int mode, Dwarf_Handler errhand, Dwarf_Ptr errarg,
+    Dwarf_Debug *ret_dbg, Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+	int ret;
+
+	if (elf == NULL || ret_dbg == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (mode != DW_DLC_READ) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (_dwarf_alloc(&dbg, mode, error) != DW_DLE_NONE)
+		return (DW_DLV_ERROR);
+
+	if (_dwarf_elf_init(dbg, elf, error) != DW_DLE_NONE) {
+		free(dbg);
+		return (DW_DLV_ERROR);
+	}
+
+	if ((ret = _dwarf_init(dbg, 0, errhand, errarg, error)) !=
+	    DW_DLE_NONE) {
+		_dwarf_elf_deinit(dbg);
+		free(dbg);
+		if (ret == DW_DLE_DEBUG_INFO_NULL)
+			return (DW_DLV_NO_ENTRY);
+		else
+			return (DW_DLV_ERROR);
+	}
+
+	*ret_dbg = dbg;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_elf(Dwarf_Debug dbg, Elf **elf, Dwarf_Error *error)
+{
+	Dwarf_Elf_Object *e;
+
+	if (dbg == NULL || elf == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	e = dbg->dbg_iface->object;
+	*elf = e->eo_elf;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_init(int fd, int mode, Dwarf_Handler errhand, Dwarf_Ptr errarg,
+    Dwarf_Debug *ret_dbg, Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+	Elf *elf;
+	int ret;
+
+	if (fd < 0 || ret_dbg == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (mode != DW_DLC_READ) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (elf_version(EV_CURRENT) == EV_NONE) {
+		DWARF_SET_ELF_ERROR(NULL, error);
+		return (DW_DLV_ERROR);
+	}
+
+	if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
+		DWARF_SET_ELF_ERROR(NULL, error);
+		return (DW_DLV_ERROR);
+	}
+
+	if (_dwarf_alloc(&dbg, mode, error) != DW_DLE_NONE)
+		return (DW_DLV_ERROR);
+
+	if (_dwarf_elf_init(dbg, elf, error) != DW_DLE_NONE) {
+		free(dbg);
+		return (DW_DLV_ERROR);
+	}
+
+	if ((ret = _dwarf_init(dbg, 0, errhand, errarg, error)) !=
+	    DW_DLE_NONE) {
+		_dwarf_elf_deinit(dbg);
+		free(dbg);
+		if (ret == DW_DLE_DEBUG_INFO_NULL)
+			return (DW_DLV_NO_ENTRY);
+		else
+			return (DW_DLV_ERROR);
+	}
+
+	*ret_dbg = dbg;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_object_init(Dwarf_Obj_Access_Interface *iface, Dwarf_Handler errhand,
+    Dwarf_Ptr errarg, Dwarf_Debug *ret_dbg, Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+
+	if (iface == NULL || ret_dbg == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (_dwarf_alloc(&dbg, DW_DLC_READ, error) != DW_DLE_NONE)
+		return (DW_DLV_ERROR);
+
+	dbg->dbg_iface = iface;
+
+	if (_dwarf_init(dbg, 0, errhand, errarg, error) != DW_DLE_NONE) {
+		free(dbg);
+		return (DW_DLV_ERROR);
+	}
+
+	*ret_dbg = dbg;
+
+	return (DW_DLV_OK);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_lineno.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,202 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_lineno.3 2074 2011-10-27 03:34:33Z jkoshy $
+.\"
+.Dd February 5, 2011
+.Os
+.Dt DWARF_LINENO 3
+.Sh NAME
+.Nm dwarf_lineaddr ,
+.Nm dwarf_linebeginstatement ,
+.Nm dwarf_lineblock ,
+.Nm dwarf_lineendsequence ,
+.Nm dwarf_lineno ,
+.Nm dwarf_lineoff ,
+.Nm dwarf_linesrc ,
+.Nm dwarf_line_srcfileno
+.Nd retrieve information associated with a DWARF line descriptor
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_lineaddr
+.Fa "Dwarf_Line ln"
+.Fa "Dwarf_Addr *ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_linebeginstatement
+.Fa "Dwarf_Line ln"
+.Fa "Dwarf_Bool *ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_lineblock
+.Fa "Dwarf_Line ln"
+.Fa "Dwarf_Bool *ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_lineendsequence
+.Fa "Dwarf_Line ln"
+.Fa "Dwarf_Bool *ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_lineno
+.Fa "Dwarf_Line ln"
+.Fa "Dwarf_Unsigned *ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_lineoff
+.Fa "Dwarf_Line ln"
+.Fa "Dwarf_Signed *ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_linesrc
+.Fa "Dwarf_Line ln"
+.Fa "char **ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_line_srcfileno
+.Fa "Dwarf_Line ln"
+.Fa "Dwarf_Unsigned *ret"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+These functions retrieve specific line information associated with
+the line descriptor specified by argument
+.Ar ln ,
+and stores it in the location pointed to by argument
+.Ar ret .
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Pp
+Function
+.Fn dwarf_lineaddr
+stores the program address corresponding to the source line specified
+in argument
+.Ar ln
+into the location pointed to by argument
+.Ar ret .
+.Pp
+Function
+.Fn dwarf_linebeginstatement
+sets the location pointed to by argument
+.Ar ret
+to 1 if the source line specified by the line descriptor
+.Ar ln
+is the beginning of a statement, or to 0 otherwise.
+.Pp
+Function
+.Fn dwarf_lineblock
+sets the location pointed to by argument
+.Ar ret
+to 1 if the source line specified by the line descriptor
+.Ar ln
+is the beginning of a basic block, or to 0 otherwise.
+.Pp
+Function
+.Fn dwarf_lineendsequence
+sets the location pointed to by argument
+.Ar ret
+to 1 if the program address associated with the line descriptor
+.Ar ln
+is the address immediately following the end of a sequence of target
+machine instructions, or to 0 otherwise.
+.Pp
+Function
+.Fn dwarf_lineno
+stores the line number of the source line associated with the line
+descriptor
+.Ar ln
+into the location pointed to by argument
+.Ar ret .
+.Pp
+Function
+.Fn dwarf_lineoff
+stores the column number within a line associated with descriptor
+.Ar ln
+into the location pointed to by argument
+.Ar ret .
+The retrieved column numbers are 1-based, with the value -1 indicating
+that column number information was not available.
+.Pp
+Function
+.Fn dwarf_linesrc
+stores a pointer to a NUL-terminated string containing the source file
+name associated with line descriptor
+.Ar ln
+into the location pointed to by argument
+.Ar ret .
+The full path of the source file is returned if possible.
+The memory used for the source file name string is managed by the DWARF(3)
+library and should not be directly freed by application code.
+Instead, portable code should use
+.Xr dwarf_dealloc 3
+to indicate that the string should be freed.
+.Pp
+Function
+.Fn dwarf_line_srcfileno
+stores the index of the source file associated with the line descriptor
+.Ar ln
+in the location pointed to by argument
+.Ar ret .
+The returned value is 1-based index into the array of source file
+names returned by
+.Xr dwarf_srcfiles 3 .
+.Sh RETURN VALUES
+On success, these functions returns
+.Dv DW_DLV_OK .
+In case of an error, they return
+.Dv DW_DLV_ERROR
+and set the argument
+.Ar err .
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_LINE_FILE_NUM_BAD"
+.It Bq Er DW_DLE_ARGUMENT
+Either of the arguments
+.Va ln
+or
+.Va ret
+was NULL.
+.It Bq Er DW_DLE_LINE_FILE_NUM_BAD
+The source file name associated with the line descriptor
+.Ar ln
+could not be retrieved by function
+.Fn dwarf_linesrc .
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_dealloc 3 ,
+.Xr dwarf_srcfiles 3 ,
+.Xr dwarf_srclines 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_lineno.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,294 @@
+/*-
+ * Copyright (c) 2009,2011 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_lineno.c 2983 2014-02-09 00:24:31Z kaiwang27 $");
+
+int
+dwarf_srclines(Dwarf_Die die, Dwarf_Line **linebuf, Dwarf_Signed *linecount,
+    Dwarf_Error *error)
+{
+	Dwarf_LineInfo li;
+	Dwarf_Debug dbg;
+	Dwarf_Line ln;
+	Dwarf_CU cu;
+	Dwarf_Attribute at; 
+	int i;
+
+	dbg = die != NULL ? die->die_dbg : NULL;
+
+	if (die == NULL || linebuf == NULL || linecount == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if ((at = _dwarf_attr_find(die, DW_AT_stmt_list)) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	cu = die->die_cu;
+	if (cu->cu_lineinfo == NULL) {
+		if (_dwarf_lineno_init(die, at->u[0].u64, error) !=
+		    DW_DLE_NONE)
+			return (DW_DLV_ERROR);
+	}
+	if (cu->cu_lineinfo == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	li = cu->cu_lineinfo;
+	*linecount = (Dwarf_Signed) li->li_lnlen;
+
+	if (*linecount == 0) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	if (li->li_lnarray != NULL) {
+		*linebuf = li->li_lnarray;
+		return (DW_DLV_OK);
+	}
+
+	if ((li->li_lnarray = malloc(*linecount * sizeof(Dwarf_Line))) ==
+	    NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLV_ERROR);
+	}
+
+	for (i = 0, ln = STAILQ_FIRST(&li->li_lnlist);
+	     i < *linecount && ln != NULL; i++, ln = STAILQ_NEXT(ln, ln_next))
+		li->li_lnarray[i] = ln;
+
+	*linebuf = li->li_lnarray;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_srcfiles(Dwarf_Die die, char ***srcfiles, Dwarf_Signed *srccount,
+    Dwarf_Error *error)
+{
+	Dwarf_LineInfo li;
+	Dwarf_LineFile lf;
+	Dwarf_Debug dbg;
+	Dwarf_CU cu;
+	Dwarf_Attribute at; 
+	int i;
+
+	dbg = die != NULL ? die->die_dbg : NULL;
+
+	if (die == NULL || srcfiles == NULL || srccount == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if ((at = _dwarf_attr_find(die, DW_AT_stmt_list)) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	cu = die->die_cu;
+	if (cu->cu_lineinfo == NULL) {
+		if (_dwarf_lineno_init(die, at->u[0].u64, error) !=
+		    DW_DLE_NONE)
+			return (DW_DLV_ERROR);
+	}
+	if (cu->cu_lineinfo == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	li = cu->cu_lineinfo;
+	*srccount = (Dwarf_Signed) li->li_lflen;
+
+	if (*srccount == 0) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	if (li->li_lfnarray != NULL) {
+		*srcfiles = li->li_lfnarray;
+		return (DW_DLV_OK);
+	}
+
+	if ((li->li_lfnarray = malloc(*srccount * sizeof(char *))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLV_ERROR);
+	}
+
+	for (i = 0, lf = STAILQ_FIRST(&li->li_lflist);
+	     i < *srccount && lf != NULL; i++, lf = STAILQ_NEXT(lf, lf_next)) {
+		if (lf->lf_fullpath)
+			li->li_lfnarray[i] = lf->lf_fullpath;
+		else
+			li->li_lfnarray[i] = lf->lf_fname;
+	}
+
+	*srcfiles = li->li_lfnarray;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_linebeginstatement(Dwarf_Line ln, Dwarf_Bool *ret_bool,
+    Dwarf_Error *error)
+{
+
+	if (ln == NULL || ret_bool == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*ret_bool = ln->ln_stmt;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_lineendsequence(Dwarf_Line ln, Dwarf_Bool *ret_bool, Dwarf_Error *error)
+{
+
+	if (ln == NULL || ret_bool == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*ret_bool = ln->ln_endseq;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_lineno(Dwarf_Line ln, Dwarf_Unsigned *ret_lineno, Dwarf_Error *error)
+{
+
+	if (ln == NULL || ret_lineno == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*ret_lineno = ln->ln_lineno;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_line_srcfileno(Dwarf_Line ln, Dwarf_Unsigned *ret_fileno,
+    Dwarf_Error *error)
+{
+
+	if (ln == NULL || ret_fileno == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*ret_fileno = ln->ln_fileno;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_lineaddr(Dwarf_Line ln, Dwarf_Addr *ret_lineaddr, Dwarf_Error *error)
+{
+
+	if (ln == NULL || ret_lineaddr == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*ret_lineaddr = ln->ln_addr;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_lineoff(Dwarf_Line ln, Dwarf_Signed *ret_lineoff, Dwarf_Error *error)
+{
+
+	if (ln == NULL || ret_lineoff == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (ln->ln_column == 0)
+		*ret_lineoff = -1;
+	else
+		*ret_lineoff = (Dwarf_Signed) ln->ln_column;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_linesrc(Dwarf_Line ln, char **ret_linesrc, Dwarf_Error *error)
+{
+	Dwarf_LineInfo li;
+	Dwarf_LineFile lf;
+	int i;
+
+	if (ln == NULL || ret_linesrc == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	li = ln->ln_li;
+	assert(li != NULL);
+
+	for (i = 1, lf = STAILQ_FIRST(&li->li_lflist);
+	     (Dwarf_Unsigned) i < ln->ln_fileno && lf != NULL;
+	     i++, lf = STAILQ_NEXT(lf, lf_next))
+		;
+
+	if (lf == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_LINE_FILE_NUM_BAD);
+		return (DW_DLV_ERROR);
+	}
+
+	if (lf->lf_fullpath) {
+		*ret_linesrc = (char *) lf->lf_fullpath;
+		return (DW_DLV_OK);
+	}
+
+	*ret_linesrc = lf->lf_fname;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_lineblock(Dwarf_Line ln, Dwarf_Bool *ret_bool, Dwarf_Error *error)
+{
+
+	if (ln == NULL || ret_bool == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*ret_bool = ln->ln_bblock;
+
+	return (DW_DLV_OK);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_lne_end_sequence.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,100 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_lne_end_sequence.3 2074 2011-10-27 03:34:33Z jkoshy $
+.\"
+.Dd September 15, 2011
+.Os
+.Dt DWARF_LNE_END_SEQUENCE 3
+.Sh NAME
+.Nm dwarf_lne_end_sequence
+.Nd set the end of instruction sequence
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "Dwarf_Unsigned"
+.Fo dwarf_lne_end_sequence
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_Addr addr"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_lne_end_sequence
+sets the address that indicates the end of a sequence of target machine
+instructions.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar addr
+specifies an address value which is the first byte after the end of a
+instruction sequence.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_lne_end_sequence
+returns
+.Dv DW_DLV_OK .
+In case of an error, function
+.Fn dwarf_lne_end_sequence
+returns
+.Dv DW_DLV_NOCOUNT
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_lne_end_sequence
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Ar dbg
+was NULL.
+.It Bq Er DW_DLE_ARGUMENT
+The value in argument
+.Ar addr
+overlapped an existing line information entry.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_directory_decl 3 ,
+.Xr dwarf_add_file_decl 3 ,
+.Xr dwarf_add_line_entry 3 ,
+.Xr dwarf_lne_set_address 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_lne_set_address.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,105 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_lne_set_address.3 2074 2011-10-27 03:34:33Z jkoshy $
+.\"
+.Dd September 14, 2011
+.Os
+.Dt DWARF_LNE_SET_ADDRESS 3
+.Sh NAME
+.Nm dwarf_lne_set_address
+.Nd set the base address for line number information
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "Dwarf_Unsigned"
+.Fo dwarf_lne_set_address
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_Addr off"
+.Fa "Dwarf_Unsigned symndx"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_lne_set_address
+sets the base address used by subsequent invocations of the
+.Xr dwarf_add_line_entry 3
+function.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar off
+specifies a relocatable program address.
+.Pp
+Argument
+.Ar symndx
+specifies the index of the ELF symbol to be used for relocation.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_lne_set_address
+returns
+.Dv DW_DLV_OK .
+In case of an error, function
+.Fn dwarf_lne_set_address
+returns
+.Dv DW_DLV_NOCOUNT
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_lne_set_address
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Ar dbg
+was NULL.
+.It Bq Er DW_DLE_ARGUMENT
+The argument
+.Ar symndx
+had an illegal value.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_directory_decl 3 ,
+.Xr dwarf_add_file_decl 3 ,
+.Xr dwarf_add_line_entry 3 ,
+.Xr dwarf_lne_end_sequence 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_loclist.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,230 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_loclist.3 2122 2011-11-09 15:35:14Z jkoshy $
+.\"
+.Dd November 9, 2011
+.Os
+.Dt DWARF_LOCLIST 3
+.Sh NAME
+.Nm dwarf_loclist ,
+.Nm dwarf_loclist_n
+.Nd retrieve DWARF location expression information
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_loclist
+.Fa "Dwarf_Attribute at"
+.Fa "Dwarf_Locdesc **llbuf"
+.Fa "Dwarf_Signed *listlen"
+.Fa "Dwarf_Error *error"
+.Fc
+.Ft int
+.Fo dwarf_loclist_n
+.Fa "Dwarf_Attribute at"
+.Fa "Dwarf_Locdesc ***llbuf"
+.Fa "Dwarf_Signed *listlen"
+.Fa "Dwarf_Error *error"
+.Fc
+.Sh DESCRIPTION
+These functions retrieve the location expressions
+associated with a DWARF attribute.
+.Pp
+Note: function
+.Fn dwarf_loclist
+is deprecated.
+New application code should instead use function
+.Fn dwarf_loclist_n
+.Pp
+Function
+.Fn dwarf_loclist_n
+retrieves the list of location expressions associated with a DWARF
+attribute.
+Argument
+.Ar at
+should reference a valid DWARF attribute.
+Argument
+.Ar llbuf
+should point to a location which will hold a returned array of
+pointers to
+.Vt Dwarf_Locdesc
+descriptors.
+Argument
+.Ar listlen
+should point to a location which will be set to the number of
+elements contained in the returned array.
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Pp
+Function
+.Fn dwarf_loclist
+retrieves the first location expression associated with an attribute.
+Argument
+.Ar at
+should reference a valid DWARF attribute.
+Argument
+.Ar llbuf
+should point to a location which will hold the returned pointer
+to a
+.Vt Dwarf_Locdesc
+descriptor.
+Argument
+.Ar listlen
+should point to a location which will be always set to 1.
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Pp
+.Vt Dwarf_Locdesc
+descriptors are defined in the header file
+.In libdwarf.h ,
+and consist of following fields:
+.Pp
+.Bl -tag -width ".Va ld_cents" -compact
+.It Va ld_lopc
+The lowest program counter address covered by the descriptor.
+This field will be set to 0 if the descriptor is not associated with
+an address range.
+.It Va ld_hipc
+The highest program counter address covered by the descriptor.
+This field will be set to 0 if the descriptor is not associated with
+an address range.
+.It Va ld_cents
+The number of entries returned in
+.Va ld_s
+field.
+.It Va ld_s
+Pointer to an array of
+.Vt Dwarf_Loc
+descriptors.
+.El
+.Pp
+Each
+.Vt Dwarf_Loc
+descriptor represents one operation of a location expression.
+These descriptors are defined in the header file
+.In libdwarf.h ,
+and consist of following fields:
+.Pp
+.Bl -tag -width ".Va lr_number2" -compact
+.It Va lr_atom
+The operator name, one of the
+.Dv DW_OP_*
+constants defined in the header file
+.In dwarf.h .
+.It Va lr_number
+The first operand of this operation.
+.It Va lr_number2
+The second operand of this operation.
+.It Va lr_offset
+The byte offset of this operation within the containing location
+expression.
+.El
+.Ss Memory Management
+The memory area used for the descriptor array returned in argument
+.Ar llbuf
+is allocated by the
+.Lb libdwarf .
+When the descriptor array is no longer needed, application code should
+use function
+.Xr dwarf_dealloc 3
+to free the memory area in the following manner:
+.Bl -enum
+.It
+First, the
+.Ar ld_s
+field of each
+.Vt Dwarf_Locdesc
+descriptor should be deallocated using the allocation type
+.Dv DW_DLA_LOC_BLOCK .
+.It
+Then, the application should free each
+.Vt Dwarf_Locdesc
+descriptor using the allocation type
+.Dv DW_DLA_LOCDESC .
+.It
+Finally, the
+.Va llbuf
+pointer should be deallocated using the allocation type
+.Dv DW_DLA_LIST .
+.El
+.Sh RETURN VALUES
+On success, these functions returns
+.Dv DW_DLV_OK .
+In case of an error, they return
+.Dv DW_DLV_ERROR
+and set the argument
+.Ar err .
+.Sh ERRORS
+These functions can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar at ,
+.Ar llbuf
+or
+.Ar listlen
+was NULL.
+.It Bq Er DW_DLE_ARGUMENT
+The attribute provided by argument
+.Ar at
+does not contain a location expression or is not associated with a
+location expression list.
+.El
+.Sh EXAMPLE
+To retrieve the location list associated with an attribute, use:
+.Bd -literal -offset indent
+Dwarf_Attribute at;
+Dwarf_Locdesc **llbuf;
+Dwarf_Signed lcnt;
+Dwarf_Loc *lr;
+Dwarf_Error de;
+int i;
+
+if (dwarf_loclist_n(at, &llbuf, &lcnt, &de) != DW_DLV_OK)
+	errx(EXIT_FAILURE, "dwarf_loclist_n failed: %s",
+	    dwarf_errmsg(de));
+
+for (i = 0; i < lcnt; i++) {
+	/* ... Use llbuf[i] ... */
+	for (j = 0; (Dwarf_Half) j < llbuf[i]->ld_cents; j++) {
+		lr = &llbuf[i]->ld_s[j];
+		/* ... Use each Dwarf_Loc descriptor ... */
+	}
+	dwarf_dealloc(dbg, llbuf[i]->ld_s, DW_DLA_LOC_BLOCK);
+	dwarf_dealloc(dbg, llbuf[i], DW_DLA_LOCDESC);
+}
+dwarf_dealloc(dbg, llbuf, DW_DLA_LIST);
+.Ed
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_dealloc 3 ,
+.Xr dwarf_loclist_from_expr 3 ,
+.Xr dwarf_loclist_from_expr_a 3 ,
+.Xr dwarf_get_loclist_entry 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_loclist.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,302 @@
+/*-
+ * Copyright (c) 2009,2014 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_loclist.c 3066 2014-06-06 19:36:06Z kaiwang27 $");
+
+static int
+copy_locdesc(Dwarf_Debug dbg, Dwarf_Locdesc *dst, Dwarf_Locdesc *src,
+    Dwarf_Error *error)
+{
+
+	assert(src != NULL && dst != NULL);
+
+	dst->ld_lopc = src->ld_lopc;
+	dst->ld_hipc = src->ld_hipc;
+	dst->ld_cents = src->ld_cents;
+
+	if (dst->ld_cents > 0) {
+		dst->ld_s = calloc(dst->ld_cents, sizeof(Dwarf_Loc));
+		if (dst->ld_s == NULL) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+			return (DW_DLE_MEMORY);
+		}
+		memcpy(dst->ld_s, src->ld_s, src->ld_cents *
+		    sizeof(Dwarf_Loc));
+	} else
+		dst->ld_s = NULL;
+
+	return (DW_DLE_NONE);
+}
+
+int
+dwarf_loclist_n(Dwarf_Attribute at, Dwarf_Locdesc ***llbuf,
+    Dwarf_Signed *listlen, Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+	int ret;
+
+	dbg = at != NULL ? at->at_die->die_dbg : NULL;
+
+	if (at == NULL || llbuf == NULL || listlen == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	switch (at->at_attrib) {
+	case DW_AT_location:
+	case DW_AT_string_length:
+	case DW_AT_return_addr:
+	case DW_AT_data_member_location:
+	case DW_AT_frame_base:
+	case DW_AT_segment:
+	case DW_AT_static_link:
+	case DW_AT_use_location:
+	case DW_AT_vtable_elem_location:
+		switch (at->at_form) {
+		case DW_FORM_data4:
+		case DW_FORM_data8:
+			/*
+			 * DW_FORM_data[48] can not be used as section offset
+			 * since DWARF4. For DWARF[23], the application needs
+			 * to determine if DW_FORM_data[48] is representing
+			 * a constant or a section offset.
+			 */
+			if (at->at_die->die_cu->cu_version >= 4) {
+				DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+				return (DW_DLV_NO_ENTRY);
+			}
+			/* FALLTHROUGH */
+		case DW_FORM_sec_offset:
+			ret = _dwarf_loclist_find(dbg, at->at_die->die_cu,
+			    at->u[0].u64, llbuf, listlen, NULL, error);
+			if (ret == DW_DLE_NO_ENTRY) {
+				DWARF_SET_ERROR(dbg, error, ret);
+				return (DW_DLV_NO_ENTRY);
+			}
+			if (ret != DW_DLE_NONE)
+				return (DW_DLV_ERROR);
+			return (DW_DLV_OK);
+		case DW_FORM_block:
+		case DW_FORM_block1:
+		case DW_FORM_block2:
+		case DW_FORM_block4:
+		case DW_FORM_exprloc:
+			if (at->at_ld == NULL) {
+				ret = _dwarf_loc_add(at->at_die, at, error);
+				if (ret != DW_DLE_NONE)
+					return (DW_DLV_ERROR);
+			}
+			*llbuf = calloc(1, sizeof(Dwarf_Locdesc *));
+			if (*llbuf == NULL) {
+				DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+				return (DW_DLV_ERROR);
+			}
+			(*llbuf)[0] = calloc(1, sizeof(Dwarf_Locdesc));
+			if ((*llbuf)[0] == NULL) {
+				free(*llbuf);
+				DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+				return (DW_DLV_ERROR);
+			}
+			if (copy_locdesc(dbg, (*llbuf)[0], at->at_ld, error) !=
+			    DW_DLE_NONE) {
+				free((*llbuf)[0]);
+				free(*llbuf);
+				return (DW_DLV_ERROR);
+			}
+			*listlen = 1;
+			return (DW_DLV_OK);
+		default:
+			/* Malformed Attr? */
+			DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
+			return (DW_DLV_NO_ENTRY);
+		}
+	default:
+		/* Wrong attr supplied. */
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+}
+
+int
+dwarf_loclist(Dwarf_Attribute at, Dwarf_Locdesc **llbuf,
+    Dwarf_Signed *listlen, Dwarf_Error *error)
+{
+	Dwarf_Locdesc **_llbuf;
+	int i, ret;
+
+	ret = dwarf_loclist_n(at, &_llbuf, listlen, error);
+	if (ret != DW_DLV_OK)
+		return (ret);
+
+	/* Only return the first location description of the list. */
+	*llbuf = _llbuf[0];
+
+	/* Free the rest of the list. */
+	for (i = 1; i < *listlen; i++) {
+		if (_llbuf[i]->ld_s)
+			free(_llbuf[i]->ld_s);
+		free(_llbuf[i]);
+	}
+	free(_llbuf);
+
+	*listlen = 1;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_loclist_entry(Dwarf_Debug dbg, Dwarf_Unsigned offset,
+    Dwarf_Addr *hipc, Dwarf_Addr *lopc, Dwarf_Ptr *data,
+    Dwarf_Unsigned *entry_len, Dwarf_Unsigned *next_entry,
+    Dwarf_Error *error)
+{
+	Dwarf_Locdesc *ld, **llbuf;
+	Dwarf_Section *ds;
+	Dwarf_Signed listlen;
+	int i, ret;
+
+	/*
+	 * Note that this API sometimes will not work correctly because
+	 * it assumes that all units have the same pointer size and offset
+	 * size.
+	 */
+
+	if (dbg == NULL || hipc == NULL || lopc == NULL || data == NULL ||
+	    entry_len == NULL || next_entry == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	ret = _dwarf_loclist_find(dbg, STAILQ_FIRST(&dbg->dbg_cu), offset,
+	    &llbuf, &listlen, entry_len, error);
+	if (ret == DW_DLE_NO_ENTRY) {
+		DWARF_SET_ERROR(dbg, error, DW_DLV_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	} else if (ret != DW_DLE_NONE)
+		return (DW_DLV_ERROR);
+
+	*hipc = *lopc = 0;
+	for (i = 0; i < listlen; i++) {
+		ld = llbuf[i];
+		if (i == 0) {
+			*hipc = ld->ld_hipc;
+			*lopc = ld->ld_lopc;
+		} else {
+			if (ld->ld_lopc < *lopc)
+				*lopc = ld->ld_lopc;
+			if (ld->ld_hipc > *hipc)
+				*hipc = ld->ld_hipc;
+		}
+	}
+
+	ds = _dwarf_find_section(dbg, ".debug_loc");
+	assert(ds != NULL);
+	*data = (uint8_t *) ds->ds_data + offset;
+	*next_entry = offset + *entry_len;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_loclist_from_expr(Dwarf_Debug dbg, Dwarf_Ptr bytes_in,
+    Dwarf_Unsigned bytes_len, Dwarf_Locdesc **llbuf, Dwarf_Signed *listlen,
+    Dwarf_Error *error)
+{
+
+	return (dwarf_loclist_from_expr_a(dbg, bytes_in, bytes_len,
+	    dbg->dbg_pointer_size, llbuf, listlen, error));
+}
+
+int
+dwarf_loclist_from_expr_a(Dwarf_Debug dbg, Dwarf_Ptr bytes_in,
+    Dwarf_Unsigned bytes_len, Dwarf_Half addr_size, Dwarf_Locdesc **llbuf,
+    Dwarf_Signed *listlen, Dwarf_Error *error)
+{
+	Dwarf_Half offset_size;
+	Dwarf_Small version;
+
+	/*
+	 * Obtain offset size and DWARF version from the current
+	 * Compilation Unit or Type Unit. These values are needed
+	 * for correctly parsing DW_OP_GNU_implicit_pointer operator.
+	 *
+	 * Note that dwarf_loclist_from_expr_b() should be used instead
+	 * if the application knows correct values for offset size
+	 * and DWARF version.
+	 */
+	if (dbg->dbg_cu_current) {
+		offset_size = dbg->dbg_cu_current->cu_length_size == 4 ? 4 : 8;
+		version = dbg->dbg_cu_current->cu_version;
+	} else if (dbg->dbg_tu_current) {
+		offset_size = dbg->dbg_tu_current->cu_length_size == 4 ? 4 : 8;
+		version = dbg->dbg_tu_current->cu_version;
+	} else {
+		/* Default values if no CU/TU context. */
+		offset_size = 4;
+		version = 2;	/* DWARF2 */
+	}
+
+	return (dwarf_loclist_from_expr_b(dbg, bytes_in, bytes_len, addr_size,
+	    offset_size, version, llbuf, listlen, error));
+}
+
+int
+dwarf_loclist_from_expr_b(Dwarf_Debug dbg, Dwarf_Ptr bytes_in,
+    Dwarf_Unsigned bytes_len, Dwarf_Half addr_size, Dwarf_Half offset_size,
+    Dwarf_Small version, Dwarf_Locdesc **llbuf, Dwarf_Signed *listlen,
+    Dwarf_Error *error)
+{
+	Dwarf_Locdesc *ld;
+	int ret;
+
+	if (dbg == NULL || bytes_in == NULL || bytes_len == 0 ||
+	    llbuf == NULL || listlen == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (addr_size != 4 && addr_size != 8) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (offset_size != 4 && offset_size != 8) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	ret = _dwarf_loc_fill_locexpr(dbg, &ld, bytes_in, bytes_len, addr_size,
+	    offset_size, version, error);
+	if (ret != DW_DLE_NONE)
+		return (DW_DLV_ERROR);
+
+	*llbuf = ld;
+	*listlen = 1;
+
+	return (DW_DLV_OK);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_loclist_from_expr.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,201 @@
+.\" Copyright (c) 2011,2014 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_loclist_from_expr.3 3129 2014-12-21 20:06:26Z jkoshy $
+.\"
+.Dd December 21, 2014
+.Os
+.Dt DWARF_LOCLIST_FROM_EXPR 3
+.Sh NAME
+.Nm dwarf_loclist_from_expr ,
+.Nm dwarf_loclist_from_expr_a ,
+.Nm dwarf_loclist_from_expr_b
+.Nd translate DWARF location expression bytes
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_loclist_from_expr
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Ptr bytes_in"
+.Fa "Dwarf_Unsigned bytes_len"
+.Fa "Dwarf_Locdesc **llbuf"
+.Fa "Dwarf_Signed *listlen"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_loclist_from_expr_a
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Ptr bytes_in"
+.Fa "Dwarf_Unsigned bytes_len"
+.Fa "Dwarf_Half addr_size"
+.Fa "Dwarf_Locdesc **llbuf"
+.Fa "Dwarf_Signed *listlen"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_loclist_from_expr_b
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Ptr bytes_in"
+.Fa "Dwarf_Unsigned bytes_len"
+.Fa "Dwarf_Half addr_size"
+.Fa "Dwarf_Half offset_size"
+.Fa "Dwarf_Small version"
+.Fa "Dwarf_Locdesc **llbuf"
+.Fa "Dwarf_Signed *listlen"
+.Fa "Dwarf_Error *error"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_loclist_from_expr
+translates DWARF location expression bytes into a
+.Vt Dwarf_Locdesc
+descriptor.
+The size for address related data is taken to be the default address
+size for the object being read.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF debug context allocated using
+.Xr dwarf_init 3 .
+.Pp
+Argument
+.Ar bytes_in
+should point to an array of DWARF location expression bytes.
+.Pp
+Argument
+.Ar bytes_len
+should specify the number of the location expression bytes to be
+translated.
+.Pp
+Argument
+.Ar llbuf
+should point to a location which will be set to a pointer
+to a returned
+.Vt Dwarf_Locdesc
+descriptor.
+.Pp
+Argument
+.Ar listlen
+should point to a location which will hold the number of the
+.Vt Dwarf_Locdesc
+descriptors returned.
+In this case it is always set to 1.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Pp
+Function
+.Fn dwarf_loclist_from_expr_a
+is identical to function
+.Fn dwarf_loclist_from_expr ,
+except that it requires one additional argument
+.Ar addr_size ,
+which specifies the address size to use when translating the location
+expression bytes.
+.Pp
+Function
+.Fn dwarf_loclist_from_expr_b
+is identical to function
+.Fn dwarf_loclist_from_expr_a
+except that it requires two additional arguments for translating the
+location expression bytes.
+Argument
+.Ar offset_size
+specifies the offset size, and argument
+.Ar version
+specifies the DWARF version.
+These values are required to correctly translate the
+.Dv DW_OP_GNU_implicit_pointer
+opcode.
+.Ss Memory Management
+The memory area used for the descriptor returned in argument
+.Ar llbuf
+is allocated by
+.Lb libdwarf .
+When the descriptor is no longer needed, application code should use
+function
+.Xr dwarf_dealloc 3
+to free the memory area in two steps:
+.Bl -enum -compact
+.It
+First, the array of
+.Vt Dwarf_Loc
+descriptors pointed to by the
+.Ar ld_s
+field of the
+.Vt Dwarf_Locdesc
+descriptor should be deallocated using the allocation type
+.Dv DW_DLA_LOC_BLOCK .
+.It
+Next, the application should free the
+.Ar llbuf
+pointer using the allocation type
+.Dv DW_DLA_LOCDESC .
+.El
+.Sh RETURN VALUES
+On success, these functions returns
+.Dv DW_DLV_OK .
+In case of an error, they return
+.Dv DW_DLV_ERROR
+and set the argument
+.Ar err .
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_LOC_EXPR_BAD"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Va dbg ,
+.Va bytes_in ,
+.Va llbuf
+or
+.Va listlen
+was NULL.
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Ar bytes_len
+was 0.
+.It Bq Er DW_DLE_ARGUMENT
+The value of argument
+.Ar addr_size
+was invalid.
+.It Bq Er DW_DLE_LOC_EXPR_BAD
+An unknown or invalid operation was found in the location expression
+bytes provided in argument
+.Ar bytes_in .
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of
+this function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_dealloc 3 ,
+.Xr dwarf_loclist_n 3 ,
+.Xr dwarf_get_fde_info_for_all_regs3 3 ,
+.Xr dwarf_get_fde_info_for_cfa_reg3 3 ,
+.Xr dwarf_get_fde_info_for_reg3 3 ,
+.Xr dwarf_get_loclist_entry 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_macinfo.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,88 @@
+/*-
+ * Copyright (c) 2009,2011 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_macinfo.c 2074 2011-10-27 03:34:33Z jkoshy $");
+
+char *
+dwarf_find_macro_value_start(char *macro_string)
+{
+	char *p;
+
+	if (macro_string == NULL)
+		return (NULL);
+
+	p = macro_string;
+	while (*p != '\0' && *p != ' ')
+		p++;
+	if (*p == ' ')
+		p++;
+
+	return (p);
+}
+
+int
+dwarf_get_macro_details(Dwarf_Debug dbg, Dwarf_Off offset,
+    Dwarf_Unsigned max_count, Dwarf_Signed *entry_cnt,
+    Dwarf_Macro_Details **details, Dwarf_Error *error)
+{
+	Dwarf_MacroSet ms;
+	Dwarf_Unsigned cnt;
+	int i;
+
+	if (dbg == NULL || entry_cnt == NULL || details == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (STAILQ_EMPTY(&dbg->dbg_mslist)) {
+		if (_dwarf_macinfo_init(dbg, error) != DW_DLE_NONE)
+			return (DW_DLV_ERROR);
+		if (STAILQ_EMPTY(&dbg->dbg_mslist)) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+			return (DW_DLV_NO_ENTRY);
+		}
+	}
+
+	STAILQ_FOREACH(ms, &dbg->dbg_mslist, ms_next) {
+		for (i = 0; (Dwarf_Unsigned) i < ms->ms_cnt; i++)
+			if (ms->ms_mdlist[i].dmd_offset == offset) {
+				cnt = ms->ms_cnt - i;
+				if (max_count != 0 && cnt > max_count)
+					cnt = max_count;
+
+				*details = &ms->ms_mdlist[i];
+				*entry_cnt = cnt;
+
+				return (DW_DLV_OK);
+			}
+	}
+
+	DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+
+	return (DW_DLV_NO_ENTRY);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_nametbl.m4	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,159 @@
+/*-
+ * Copyright (c) 2009,2011 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: dwarf_nametbl.m4 2074 2011-10-27 03:34:33Z jkoshy $
+ */
+
+define(`MAKE_NAMETBL_API',`
+int
+dwarf_get_$1s(Dwarf_Debug dbg, Dwarf_$2 **$1s,
+    Dwarf_Signed *ret_count, Dwarf_Error *error)
+{
+	Dwarf_Section *ds;
+	int ret;
+
+	if (dbg == NULL || $1s == NULL || ret_count == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (dbg->dbg_$1s == NULL) {
+		if ((ds = _dwarf_find_section(dbg, ".debug_$4")) != NULL) {
+			ret = _dwarf_nametbl_init(dbg, &dbg->dbg_$1s, ds,
+			    error);
+			if (ret != DW_DLE_NONE)
+				return (DW_DLV_ERROR);
+		}
+		if (dbg->dbg_$1s == NULL) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+			return (DW_DLV_NO_ENTRY);
+		}
+	}
+
+	*$1s = dbg->dbg_$1s->ns_array;
+	*ret_count = dbg->dbg_$1s->ns_len;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_$3name(Dwarf_$2 $1, char **ret_name, Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+
+	dbg = $1 != NULL ? $1->np_nt->nt_cu->cu_dbg : NULL;
+
+	if ($1 == NULL || ret_name == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	*ret_name = $1->np_name;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_$1_die_offset(Dwarf_$2 $1, Dwarf_Off *ret_offset,
+    Dwarf_Error *error)
+{
+	Dwarf_NameTbl nt;
+	Dwarf_Debug dbg;
+
+	dbg = $1 != NULL ? $1->np_nt->nt_cu->cu_dbg : NULL;
+
+	if ($1 == NULL || ret_offset == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	nt = $1->np_nt;
+	assert(nt != NULL);
+
+	*ret_offset = nt->nt_cu_offset + $1->np_offset;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_$1_cu_offset(Dwarf_$2 $1, Dwarf_Off *ret_offset,
+    Dwarf_Error *error)
+{
+	Dwarf_NameTbl nt;
+	Dwarf_Debug dbg;
+
+	dbg = $1 != NULL ? $1->np_nt->nt_cu->cu_dbg : NULL;
+
+	if ($1 == NULL || ret_offset == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	nt = $1->np_nt;
+	assert(nt != NULL);
+
+	*ret_offset = nt->nt_cu_offset;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_$1_name_offsets(Dwarf_$2 $1, char **ret_name, Dwarf_Off *die_offset,
+    Dwarf_Off *cu_offset, Dwarf_Error *error)
+{
+	Dwarf_CU cu;
+	Dwarf_Debug dbg;
+	Dwarf_NameTbl nt;
+
+	dbg = $1 != NULL ? $1->np_nt->nt_cu->cu_dbg : NULL;
+
+	if ($1 == NULL || ret_name == NULL || die_offset == NULL ||
+	    cu_offset == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	nt = $1->np_nt;
+	assert(nt != NULL);
+
+	cu = nt->nt_cu;
+	assert(cu != NULL);
+
+	*ret_name = $1->np_name;
+	*die_offset = nt->nt_cu_offset + $1->np_offset;
+	*cu_offset = cu->cu_1st_offset;
+
+	return (DW_DLV_OK);
+}
+
+void
+dwarf_$1s_dealloc(Dwarf_Debug dbg, Dwarf_$2 *$1s, Dwarf_Signed count)
+{
+
+	(void) dbg;
+	(void) $1s;
+	(void) count;
+}
+')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_new_die.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,164 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_new_die.3 2074 2011-10-27 03:34:33Z jkoshy $
+.\"
+.Dd September 4, 2011
+.Os
+.Dt DWARF_NEW_DIE 3
+.Sh NAME
+.Nm dwarf_new_die
+.Nd allocate a new debugging information entry
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft Dwarf_P_Die
+.Fo dwarf_new_die
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_Tag tag"
+.Fa "Dwarf_P_Die parent"
+.Fa "Dwarf_P_Die child"
+.Fa "Dwarf_P_Die left"
+.Fa "Dwarf_P_Die right"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_new_die
+allocates a new DWARF debugging information entry and links it
+to another debugging information entry.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar tag
+should specify the tag of the newly created debugging information entry.
+Valid values for this argument are those for the
+.Dv DW_TAG_ Ns *
+symbols defined in
+.In libdwarf.h .
+.Pp
+Argument
+.Ar parent
+specifies the parent link of the debugging information entry.
+.Pp
+Argument
+.Ar child
+specifies the first child link of the debugging information entry.
+.Pp
+Argument
+.Ar left
+specifies the left sibling link of the debugging information entry.
+.Pp
+Argument
+.Ar right
+specifies the right sibling link of the debugging information entry.
+.Pp
+Only one of arguments
+.Ar parent ,
+.Ar child ,
+.Ar left
+and
+.Ar right
+is allowed to be non-NULL.
+Application code can subsequently call the function
+.Xr dwarf_die_link 3
+to change the links for the created debugging information entry.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_new_die
+returns the newly created debugging information entry.
+In case of an error, function
+.Fn dwarf_new_die
+returns
+.Dv DW_DLV_BADADDR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_new_die
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Ar dbg
+was NULL.
+.It Bq Er DW_DLE_ARGUMENT
+More than one of the arguments
+.Ar parent ,
+.Ar child ,
+.Ar left
+and
+.Ar right
+were non-NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh EXAMPLES
+To create debugging information entries and add them to the producer
+instance, use:
+.Bd -literal -offset indent
+Dwarf_P_Debug dbg;
+Dwarf_P_Die die1, die2;
+Dwarf_Error de;
+
+/* ... assume dbg refers to a DWARF producer instance ... */
+
+die1 = dwarf_new_die(dbg, DW_TAG_compilation_unit, NULL, NULL, NULL,
+    NULL, &de);
+if (die1 == NULL) {
+	warnx("dwarf_new_die failed: %s", dwarf_errmsg(-1));
+	return;
+}
+
+die2 = dwarf_new_die(dbg, DW_TAG_base_type, die1, NULL, NULL,
+    NULL, &de);
+if (die1 == NULL) {
+	warnx("dwarf_new_die failed: %s", dwarf_errmsg(-1));
+	return;
+}
+
+if (dwarf_add_die_to_debug(dbg, die1, &de) != DW_DLV_OK) {
+	warnx("dwarf_add_die_to_debug failed: %s", dwarf_errmsg(-1));
+	return;
+}
+.Ed
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_die_to_debug 3 ,
+.Xr dwarf_die_link 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_new_expr.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,135 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_new_expr.3 2074 2011-10-27 03:34:33Z jkoshy $
+.\"
+.Dd September 8, 2011
+.Os
+.Dt DWARF_NEW_EXPR 3
+.Sh NAME
+.Nm dwarf_new_expr
+.Nd create a location expression descriptor
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "Dwarf_P_Expr"
+.Fo dwarf_new_expr
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_new_expr
+allocates a DWARF location expression descriptor used to build up a
+location expression stream.
+.Pp
+The application can use the functions
+.Xr dwarf_add_expr_gen 3
+and
+.Xr dwarf_add_expr_addr_b 3
+to add location expression operators to the created descriptor.
+When done, the application can call the function
+.Xr dwarf_expr_into_block 3
+to retrieve the generated byte stream for the location expression,
+or call the function
+.Xr dwarf_add_AT_location_expr 3
+to create an attribute with the location expression stream as its
+value.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_new_expr
+returns the created location expression descriptor.
+In case of an error, function
+.Fn dwarf_new_expr
+returns
+.Dv DW_DLV_BADADDR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_new_expr
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Ar dbg
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of
+the function.
+.El
+.Sh EXAMPLES
+To create a location expression descriptor, add location expression
+operators to it and to retrieve the generated byte stream,
+use:
+.Bd -literal -offset indent
+Dwarf_P_Debug dbg;
+Dwarf_Error de;
+Dwarf_P_Expr pe;
+Dwarf_Addr buf;
+Dwarf_Unsigned len;
+
+/* ...Assume that `dbg' refers to a DWARF producer instance... */
+
+if ((pe = dwarf_new_expr(dbg, &de)) == DW_DLV_BADADDR) {
+	warnx("dwarf_new_expr failed: %s", dwarf_errmsg(-1));
+	return;
+}
+
+if (dwarf_add_expr_gen(pe, DW_OP_regx, 55, 0, &de) ==
+    DW_DLV_NOCOUNT) {
+	warnx("dwarf_add_expr_gen failed: %s", dwarf_errmsg(-1));
+	return;
+}
+
+if ((buf = dwarf_expr_into_block(pe, &len, &de)) ==
+    DW_DLV_BADADDR) {
+	warnx("dwarf_expr_into_block failed: %s",
+	    dwarf_errmsg(-1));
+	return;
+}
+.Ed
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_AT_location_expr 3 ,
+.Xr dwarf_add_expr_gen 3 ,
+.Xr dwarf_add_expr_addr 3 ,
+.Xr dwarf_add_expr_addr_b 3 ,
+.Xr dwarf_expr_current_offset 3 ,
+.Xr dwarf_expr_into_block 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_new_fde.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,87 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_new_fde.3 2074 2011-10-27 03:34:33Z jkoshy $
+.\"
+.Dd September 24, 2011
+.Os
+.Dt DWARF_NEW_FDE 3
+.Sh NAME
+.Nm dwarf_new_fde
+.Nd allocate a DWARF frame descriptor
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "Dwarf_P_Fde"
+.Fo dwarf_new_fde
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_new_fde
+allocates a new DWARF frame descriptor.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_new_fde
+returns the newly created frame descriptor.
+In case of an error, function
+.Fn dwarf_new_fde
+returns
+.Dv DW_DLV_BADADDR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_new_fde
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Ar dbg
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_fde_inst 3 ,
+.Xr dwarf_add_frame_fde 3 ,
+.Xr dwarf_add_frame_fde_b 3 ,
+.Xr dwarf_add_frame_cie 3 ,
+.Xr dwarf_fde_cfa_offset 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_next_cu_header.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,288 @@
+.\" Copyright (c) 2010,2014 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_next_cu_header.3 3182 2015-04-10 16:08:10Z emaste $
+.\"
+.Dd December 21, 2014
+.Os
+.Dt DWARF_NEXT_CU_HEADER 3
+.Sh NAME
+.Nm dwarf_next_cu_header ,
+.Nm dwarf_next_cu_header_b ,
+.Nm dwarf_next_cu_header_c
+.Nd step through compilation units in a DWARF debug context
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_next_cu_header
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Unsigned *cu_length"
+.Fa "Dwarf_Half *cu_version"
+.Fa "Dwarf_Off *cu_abbrev_offset"
+.Fa "Dwarf_Half *cu_pointer_size"
+.Fa "Dwarf_Unsigned *cu_next_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_next_cu_header_b
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Unsigned *cu_length"
+.Fa "Dwarf_Half *cu_version"
+.Fa "Dwarf_Off *cu_abbrev_offset"
+.Fa "Dwarf_Half *cu_pointer_size"
+.Fa "Dwarf_Half *cu_offset_size"
+.Fa "Dwarf_Half *cu_extension_size"
+.Fa "Dwarf_Unsigned *cu_next_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft int
+.Fo dwarf_next_cu_header_c
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Bool is_info"
+.Fa "Dwarf_Unsigned *cu_length"
+.Fa "Dwarf_Half *cu_version"
+.Fa "Dwarf_Off *cu_abbrev_offset"
+.Fa "Dwarf_Half *cu_pointer_size"
+.Fa "Dwarf_Half *cu_offset_size"
+.Fa "Dwarf_Half *cu_extension_size"
+.Fa "Dwarf_Sig8 *type_signature"
+.Fa "Dwarf_Unsigned *type_offset"
+.Fa "Dwarf_Unsigned *cu_next_offset"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+These functions are used to step through compilation or type units
+associated with a DWARF debug context, optionally returning information
+about the unit.
+.Pp
+Function
+.Fn dwarf_next_cu_header_c
+is the API recommended for new application code.
+Function
+.Fn dwarf_next_cu_header
+and
+.Fn dwarf_next_cu_header_b
+can only operate on compilation units associated with the
+.Dq \&.debug_info
+section.
+They are less general than function
+.Fn dwarf_next_cu_header_c ,
+and are deprecated for use by new application code.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF debug context allocated using
+.Xr dwarf_init 3 .
+If argument
+.Ar is_info
+is set to 1,
+the function returns information for compilation units found in the
+.Dq \&.debug_info
+section.
+If argument
+.Ar is_info
+is set to 0,
+the function returns information for type units found in the
+.Dq \&.debug_types
+sections.
+Argument
+.Ar cu_length
+should point to a location that will be set to the
+length of the compilation or type unit.
+Argument
+.Ar cu_version
+should point to a location that will be set to the
+version number for the compilation or type unit.
+Argument
+.Ar cu_abbrev_offset
+should point to a location that will be set to the
+starting offset (in the
+.Dq .debug_abbrev
+section) of the set of debugging information entry abbreviations
+associated with this compilation or type unit.
+Argument
+.Ar cu_pointer_size
+should point to a location that will be set to the
+size in bytes of an address for the machine architecture of the
+underlying object being debugged.
+Argument
+.Ar cu_offset_size
+should point to a location that will be set to the
+size in bytes for a DWARF offset in the compilation or type unit.
+Argument
+.Ar cu_extension_size
+is only needed for processing MIPS/IRIX objects that use
+a non-standard DWARF format.
+It should point to a location that will be set to 4 for normal
+objects and to 0 for non-standard ones.
+Argument
+.Ar type_signature
+and
+.Ar type_offset
+is only needed for processing type units.
+Argument
+.Ar type_signature
+should point to a location that will be set to the 64-bit unique signature
+of the type described in the type unit.
+Argument
+.Ar type_offset
+should point to a location that will be set to the offset of the debugging
+information entry that describes the type.
+Argument
+.Ar cu_next_offset
+should point to a location that will be set to the
+offset of the next compilation unit header in the
+.Dq \&.debug_info
+section,
+or the offset of the next type unit header in the
+.Dq \&.debug_types
+section.
+Argument
+.Ar err
+should point to a location that will hold an error descriptor in case
+of an error.
+.Pp
+Function
+.Fn dwarf_next_cu_header_b
+is identical to function
+.Fn dwarf_next_cu_header_c
+except that it does not provide arguments
+.Ar is_info ,
+.Ar type_signature
+and
+.Ar type_offset .
+.Pp
+Function
+.Fn dwarf_next_cu_header
+is identical to function
+.Fn dwarf_next_cu_header_b
+except that it does not provide arguments
+.Ar cu_offset_size
+and
+.Ar cu_extension_size .
+.Pp
+A value of NULL may be used for any of the arguments
+.Ar cu_length ,
+.Ar cu_version ,
+.Ar cu_abbrev_offset ,
+.Ar cu_pointer_size ,
+.Ar cu_offset_size ,
+.Ar cu_extension_size ,
+.Ar type_signature ,
+.Ar type_offset ,
+.Ar cu_next_offset
+and
+.Ar err
+if the caller is not interested in the respective value.
+.Ss Iterating Through Compilation Units in a Debug Context
+.Pp
+The first call to function
+.Fn dwarf_next_cu_header_c
+for a given debug context with argument
+.Ar is_info
+set to 1 will return information about the first
+compilation unit in the
+.Dq \&.debug_info
+section.
+Subsequent calls to the function will iterate through the remaining
+compilation units in the section.
+On stepping past the last compilation unit in the section,
+function
+.Fn dwarf_next_cu_header_c
+returns
+.Dv DW_DLV_NO_ENTRY
+and resets its internal state.
+The next call to the function will restart from the first compilation
+unit in the section.
+.Ss Iterating Through Type Units in a Debug Context
+When a DWARF debug context is allocated using
+.Xr dwarf_init 3 ,
+an internal pointer associated with the context will point to the first
+.Dq \&.debug_types
+section found in the debug object.
+The first call to function
+.Fn dwarf_next_cu_header_c
+for the debug context with argument
+.Ar is_info
+set to 0 will return information about the first
+type unit in that
+.Dq \&.debug_types
+section.
+Subsequent calls to the function will iterate through the remaining
+type units in the section.
+On stepping past the last type unit in the debug context,
+function
+.Fn dwarf_next_cu_header_c
+returns
+.Dv DW_DLV_NO_ENTRY
+and resets its internal state.
+The next call to the function will restart from the first type
+unit in the
+.Dq \&.debug_types
+section.
+.Pp
+If the debug object contains multiple
+.Dq \&.debug_types
+sections, the function
+.Fn dwarf_next_types_section
+can be called to move the internal pointer to the next
+.Dq \&.debug_types
+section.
+As a result, subsequent calls of the function
+.Fn dwarf_next_cu_header_c
+will operate on the new
+.Dq \&.debug_types
+section.
+Function
+.Fn dwarf_next_types_section
+returns
+.Dv DW_DLV_NO_ENTRY
+when there are no more
+.Dq \&.debug_types
+sections left in the debug object.
+.Sh RETURN VALUES
+On success, these functions return
+.Dv DW_DLV_OK .
+In case of an error, they return
+.Dv DW_DLV_ERROR
+and set argument
+.Ar err .
+When there are no more compilation units left to traverse, they return
+.Dv DW_DLV_NO_ENTRY .
+.Sh ERRORS
+These functions can fail with the following error:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Va dbg
+was NULL.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_cu_die_offset_given_cu_header_offset 3 ,
+.Xr dwarf_init 3 ,
+.Xr dwarf_next_types_section 3 ,
+.Xr dwarf_siblingof 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_next_types_section.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,134 @@
+.\" Copyright (c) 2014 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_next_types_section.3 3116 2014-12-20 18:26:55Z jkoshy $
+.\"
+.Dd December 20, 2014
+.Os
+.Dt DWARF_NEXT_TYPES_SECTION 3
+.Sh NAME
+.Nm dwarf_next_types_section
+.Nd step through .debug_types sections in a debug context
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_next_types_section
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_next_types_section
+steps through the
+.Dq \&.debug_types
+sections found in a debug context.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF debug context allocated using
+.Xr dwarf_init 3 .
+Argument
+.Ar err
+should point to a location that will hold an error descriptor in case
+of an error.
+.Pp
+When a DWARF debug context is allocated using
+.Xr dwarf_init 3 ,
+an internal pointer associated with the context will point to the
+first
+.Dq \&.debug_types
+section present in the debug object.
+When the application calls function
+.Fn dwarf_next_types_section ,
+this internal pointer will move to the next
+.Dq \&.debug_types
+section present.
+On stepping past the last
+.Dq \&.debug_types
+section left in the debug context, function
+.Fn dwarf_next_types_section
+returns
+.Dv DW_DLV_NO_ENTRY .
+The next call to the function will restart from the first
+.Dq \&.debug_types
+section in the debug context.
+.Pp
+Application code should call function
+.Xr dwarf_next_cu_header_c 3
+to iterate though the type units associated with the current
+.Dq \&.debug_types
+section.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_next_types_section
+returns
+.Dv DW_DLV_OK .
+.Pp
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets argument
+.Ar err .
+When there are no more
+.Dq \&.debug_types
+sections left to traverse, it returns
+.Dv DW_DLV_NO_ENTRY .
+.Sh COMPATIBILITY
+This function is an extension to the
+.Xr DWARF 3
+API.
+.Sh ERRORS
+The
+.Fn dwarf_next_types_section
+function may fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Va dbg
+was NULL.
+.El
+.Sh EXAMPLES
+To iterate though every type unit in all the
+.Dq \&.debug_types
+sections found in a debug context:
+.Bd -literal -offset indent
+Dwarf_Debug dbg;
+Dwarf_Sig8 sig8;
+Dwarf_Unsigned typeoff;
+Dwarf_Error de;
+
+\&... allocate dbg using dwarf_init() etc ...
+
+do {
+	while ((ret = dwarf_next_cu_header_c(dbg, 0, NULL, NULL, NULL,
+	    NULL, NULL, NULL, &sig8, &typeoff, NULL, &de)) == DW_DLV_OK) {
+		/* Access DIEs etc ... */
+	}
+} while (dwarf_next_types_section(dbg, &de) == DW_DLV_OK);
+.Ed
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_init 3 ,
+.Xr dwarf_next_cu_header_c 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_object_init.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,227 @@
+.\" Copyright (c) 2011 Joseph Koshy
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_object_init.3 2074 2011-10-27 03:34:33Z jkoshy $
+.\"
+.Dd September 29, 2011
+.Os
+.Dt DWARF_OBJECT_INIT 3
+.Sh NAME
+.Nm dwarf_object_init
+.Nd allocate a DWARF debug descriptor with application-specific file \
+access methods
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_object_init
+.Fa "Dwarf_Obj_Access_Interface *iface"
+.Fa "Dwarf_Handler errhand"
+.Fa "Dwarf_Ptr errarg"
+.Fa "Dwarf_Debug *dbg"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+.Pp
+The
+.Fn dwarf_object_init
+function allocates and returns a
+.Vt Dwarf_Debug
+instance that uses application-supplied access methods to read file
+content.
+.Pp
+The argument
+.Ar iface
+should point to a populated
+.Vt Dwarf_Obj_Access_Interface
+structure.
+The contents of the
+.Vt Dwarf_Obj_Access_Interface
+structure are described in the section
+.Sx "Object Access Functions"
+below.
+.Pp
+The argument
+.Ar errhand
+should point to a function to be called in case of an error.
+If this argument is
+.Dv NULL
+then a default error handling scheme is used.
+See
+.Xr dwarf 3
+for a description of the error handling schemes available.
+.Pp
+The argument
+.Ar errarg
+will be passed to the error handler function pointed to by argument
+.Ar errhand .
+.Pp
+The argument
+.Ar dbg
+should point to a memory location that will be set to a reference to
+the returned
+.Vt Dwarf_Debug
+descriptor.
+.Pp
+The argument
+.Ar err
+will be used to return a
+.Vt Dwarf_Error
+descriptor in case of an error.
+.Ss Object Access Functions
+The data structures used to specify object access methods are defined
+in
+.In libdwarf.h .
+.Bl -tag -width indent
+.It Vt "Dwarf_Obj_Access_Interface"
+This structure bundles together a set of file access methods along
+with a pointer to application-private state.
+.Bd -literal -offset indent
+typedef struct {
+	void *object;
+	const Dwarf_Obj_Access_Methods *methods;
+} Dwarf_Obj_Access_Interface;
+.Ed
+.Pp
+.Bl -tag -width ".Ar methods" -compact
+.It Ar object
+This field points to application-specific state that will be passed as
+the first parameter to the actual access object methods.
+.It Ar methods
+This structure contains pointers to the functions implementing the
+access methods, as described below.
+.El
+.It Vt Dwarf_Obj_Access_Methods
+This structure specifies the functions implementing low-level access.
+.Bd -literal -offset indent
+typedef struct {
+	int (*get_section_info)(void *obj, Dwarf_Half index,
+	    Dwarf_Obj_Access_Section *ret, int *error);
+	Dwarf_Endianness (*get_byte_order)(void *obj);
+	Dwarf_Small (*get_length_size)(void *obj);
+	Dwarf_Small (*get_pointer_size)(void *obj);
+	Dwarf_Unsigned (*get_section_count)(void *obj);
+	int (*load_section)(void *obj, Dwarf_Half ndx,
+	    Dwarf_Small **ret_data, int *error);
+} Dwarf_Obj_Access_Methods;
+.Ed
+.Pp
+.Bl -tag -width ".Ar get_section_count" -compact
+.It Ar get_byte_order
+This function should return the endianness of the DWARF object by
+returning one of the constants
+.Dv DW_OBJECT_MSB
+or
+.Dv DW_OBJECT_LSB .
+.It Ar get_length_size
+This function should return the number of bytes needed to represent a
+DWARF offset in the object being debugged.
+.It Ar get_pointer_size
+This function should return the size in bytes, in the object being
+debugged, of a memory address.
+.It Ar get_section_count
+This function should return the number of sections in the object being
+debugged.
+.It Ar get_section_info
+This function should return information about the section at the
+index
+.Ar ndx
+by filling in the structure of type
+.Vt Dwarf_Obj_Access_Section
+pointed to by argument
+.Ar ret .
+The
+.Vt Dwarf_Obj_Access_Section
+structure is described below.
+.It Ar load_section
+This function should load the section specified by argument
+.Ar ndx
+into memory and place a pointer to the section's data into
+the location pointed to by argument
+.Ar ret_data .
+.El
+.Pp
+The argument
+.Ar obj
+passed to these functions will be set to the pointer value in the
+.Ar object
+field of the associated
+.Vt Dwarf_Obj_Access_Interface
+structure.
+.Pp
+The argument
+.Ar error
+is used to return an error code in case of an error.
+.It Vt Dwarf_Obj_Access_Section
+This structure describes the layout of a section in the DWARF object.
+.Bd -literal -offset indent
+typedef struct {
+	Dwarf_Addr addr;
+	Dwarf_Unsigned size;
+	const char *name;
+} Dwarf_Obj_Access_Section;
+.Ed
+.Pp
+.Bl -tag -width ".Ar name" -compact
+.It Ar addr
+A pointer to the start of the section's data.
+.It Ar size
+The size of the section in bytes.
+.It Ar name
+A pointer to a NUL-terminated string containing the name of the
+section.
+.El
+.El
+.Sh RETURN VALUES
+On success, the
+.Fn dwarf_object_init
+function returns
+.Dv DW_DLV_OK .
+In case of an error, the function returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err.
+.Sh ERRORS
+The
+.Fn dwarf_object_init
+function may fail with the following errors:
+.Bl -tag -width ".Bq Er DW_DLE_DEBUG_INFO_NULL"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar iface
+or
+.Ar dbg
+was NULL.
+.It Bq Er DW_DLE_DEBUG_INFO_NULL
+The underlying object did not contain debugging information.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_init 3 ,
+.Xr dwarf_init_elf 3 ,
+.Xr dwarf_object_finish 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_pro_arange.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,73 @@
+/*-
+ * Copyright (c) 2010 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_pro_arange.c 2074 2011-10-27 03:34:33Z jkoshy $");
+
+Dwarf_Unsigned
+dwarf_add_arange(Dwarf_P_Debug dbg, Dwarf_Addr start, Dwarf_Unsigned length,
+    Dwarf_Signed symbol_index, Dwarf_Error *error)
+{
+
+	return (dwarf_add_arange_b(dbg, start, length, symbol_index, 0, 0,
+	    error));
+}
+
+Dwarf_Unsigned
+dwarf_add_arange_b(Dwarf_P_Debug dbg, Dwarf_Addr start, Dwarf_Unsigned length,
+    Dwarf_Unsigned symbol_index, Dwarf_Unsigned end_symbol_index,
+    Dwarf_Addr offset_from_end_symbol, Dwarf_Error *error)
+{
+	Dwarf_ArangeSet as;
+	Dwarf_Arange ar;
+
+	if (dbg == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (0);
+	}
+	as = dbg->dbgp_as;
+
+	if (end_symbol_index > 0 &&
+	    (dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) == 0) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (0);
+	}
+
+	if ((ar = calloc(1, sizeof(struct _Dwarf_Arange))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (0);
+	}
+	ar->ar_as = as;
+	ar->ar_address = start;
+	ar->ar_range = length;
+	ar->ar_symndx = symbol_index;
+	ar->ar_esymndx = end_symbol_index;
+	ar->ar_eoff = offset_from_end_symbol;
+	STAILQ_INSERT_TAIL(&as->as_arlist, ar, ar_next);
+
+	return (1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_pro_attr.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,384 @@
+/*-
+ * Copyright (c) 2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_pro_attr.c 2074 2011-10-27 03:34:33Z jkoshy $");
+
+Dwarf_P_Attribute
+dwarf_add_AT_location_expr(Dwarf_P_Debug dbg, Dwarf_P_Die die, Dwarf_Half attr,
+    Dwarf_P_Expr loc_expr, Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+
+	if (dbg == NULL || die == NULL || loc_expr == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_BADADDR);
+	}
+
+	if (_dwarf_attr_alloc(die, &at, error) != DW_DLE_NONE)
+		return (DW_DLV_BADADDR);
+
+	at->at_die = die;
+	at->at_attrib = attr;
+	at->at_expr = loc_expr;
+
+	if (_dwarf_expr_into_block(loc_expr, error) != DW_DLE_NONE)
+		return (DW_DLV_BADADDR);
+	at->u[0].u64 = loc_expr->pe_length;
+	at->u[1].u8p = loc_expr->pe_block;
+	if (loc_expr->pe_length <= UCHAR_MAX)
+		at->at_form = DW_FORM_block1;
+	else if (loc_expr->pe_length <= USHRT_MAX)
+		at->at_form = DW_FORM_block2;
+	else if (loc_expr->pe_length <= UINT_MAX)
+		at->at_form = DW_FORM_block4;
+	else
+		at->at_form = DW_FORM_block;
+
+	STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
+
+	return (at);
+}
+
+Dwarf_P_Attribute
+dwarf_add_AT_name(Dwarf_P_Die die, char *name, Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+
+	if (_dwarf_add_string_attr(die, &at, DW_AT_name, name, error) !=
+	    DW_DLE_NONE)
+		return (DW_DLV_BADADDR);
+
+	return (at);
+}
+
+Dwarf_P_Attribute
+dwarf_add_AT_comp_dir(Dwarf_P_Die die, char *dir, Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+
+	if (_dwarf_add_string_attr(die, &at, DW_AT_comp_dir, dir, error) !=
+	    DW_DLE_NONE)
+		return (DW_DLV_BADADDR);
+
+	return (at);
+}
+
+Dwarf_P_Attribute
+dwarf_add_AT_producer(Dwarf_P_Die die, char *producer, Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+
+	if (_dwarf_add_string_attr(die, &at, DW_AT_producer, producer, error) !=
+	    DW_DLE_NONE)
+		return (DW_DLV_BADADDR);
+
+	return (at);
+}
+
+Dwarf_P_Attribute
+dwarf_add_AT_const_value_signedint(Dwarf_P_Die die, Dwarf_Signed value,
+    Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+	Dwarf_Debug dbg;
+
+	dbg = die != NULL ? die->die_dbg : NULL;
+
+	if (die == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_BADADDR);
+	}
+
+	if (_dwarf_attr_alloc(die, &at, error) != DW_DLE_NONE)
+		return (DW_DLV_BADADDR);
+
+	at->at_die = die;
+	at->at_attrib = DW_AT_const_value;
+	at->at_form = DW_FORM_sdata;
+	at->u[0].s64 = value;
+
+	STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
+
+	return (at);
+}
+
+Dwarf_P_Attribute
+dwarf_add_AT_const_value_unsignedint(Dwarf_P_Die die, Dwarf_Unsigned value,
+    Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+	Dwarf_Debug dbg;
+
+	dbg = die != NULL ? die->die_dbg : NULL;
+
+	if (die == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_BADADDR);
+	}
+
+	if (_dwarf_attr_alloc(die, &at, error) != DW_DLE_NONE)
+		return (DW_DLV_BADADDR);
+
+	at->at_die = die;
+	at->at_attrib = DW_AT_const_value;
+	at->at_form = DW_FORM_udata;
+	at->u[0].u64 = value;
+
+	STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
+
+	return (at);
+}
+
+Dwarf_P_Attribute
+dwarf_add_AT_const_value_string(Dwarf_P_Die die, char *string,
+    Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+
+	if (_dwarf_add_string_attr(die, &at, DW_AT_const_value, string,
+	    error) != DW_DLE_NONE)
+		return (DW_DLV_BADADDR);
+
+	return (at);
+}
+
+Dwarf_P_Attribute
+dwarf_add_AT_targ_address(Dwarf_P_Debug dbg, Dwarf_P_Die die, Dwarf_Half attr,
+    Dwarf_Unsigned pc_value, Dwarf_Signed sym_index, Dwarf_Error *error)
+{
+
+	return (dwarf_add_AT_targ_address_b(dbg, die, attr, pc_value, sym_index,
+	    error));
+}
+
+Dwarf_P_Attribute
+dwarf_add_AT_targ_address_b(Dwarf_P_Debug dbg, Dwarf_P_Die die, Dwarf_Half attr,
+    Dwarf_Unsigned pc_value, Dwarf_Unsigned sym_index, Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+
+	if (dbg == NULL || die == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_BADADDR);
+	}
+
+	if (_dwarf_attr_alloc(die, &at, error) != DW_DLE_NONE)
+		return (DW_DLV_BADADDR);
+
+	at->at_die = die;
+	at->at_attrib = attr;
+	at->at_form = DW_FORM_addr;
+	at->at_relsym = sym_index;
+	at->u[0].u64 = pc_value;
+
+	STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
+
+	return (at);
+}
+
+Dwarf_P_Attribute
+dwarf_add_AT_dataref(Dwarf_P_Debug dbg, Dwarf_P_Die die, Dwarf_Half attr,
+    Dwarf_Unsigned pc_value, Dwarf_Unsigned sym_index, Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+	int ret;
+
+	if (dbg == NULL || die == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_BADADDR);
+	}
+
+	ret = _dwarf_add_AT_dataref(dbg, die, attr, pc_value, sym_index,
+	    NULL, &at, error);
+	if (ret != DW_DLE_NONE)
+		return (DW_DLV_BADADDR);
+
+	return (at);
+
+}
+
+Dwarf_P_Attribute
+dwarf_add_AT_ref_address(Dwarf_P_Debug dbg, Dwarf_P_Die die, Dwarf_Half attr,
+    Dwarf_Unsigned pc_value, Dwarf_Unsigned sym_index, Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+
+	if (dbg == NULL || die == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_BADADDR);
+	}
+
+	if (_dwarf_attr_alloc(die, &at, error) != DW_DLE_NONE)
+		return (DW_DLV_BADADDR);
+
+	at->at_die = die;
+	at->at_attrib = attr;
+	at->at_form = DW_FORM_ref_addr;
+	at->at_relsym = sym_index;
+	at->u[0].u64 = pc_value;
+
+	STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
+
+	return (at);
+}
+
+Dwarf_P_Attribute
+dwarf_add_AT_unsigned_const(Dwarf_P_Debug dbg, Dwarf_P_Die die, Dwarf_Half attr,
+    Dwarf_Unsigned value, Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+
+	if (dbg == NULL || die == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_BADADDR);
+	}
+
+	if (_dwarf_attr_alloc(die, &at, error) != DW_DLE_NONE)
+		return (DW_DLV_BADADDR);
+
+	at->at_die = die;
+	at->at_attrib = attr;
+	at->u[0].u64 = value;
+
+	if (value <= UCHAR_MAX)
+		at->at_form = DW_FORM_data1;
+	else if (value <= USHRT_MAX)
+		at->at_form = DW_FORM_data2;
+	else if (value <= UINT_MAX)
+		at->at_form = DW_FORM_data4;
+	else
+		at->at_form = DW_FORM_data8;
+
+	STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
+
+	return (at);
+}
+
+Dwarf_P_Attribute
+dwarf_add_AT_signed_const(Dwarf_P_Debug dbg, Dwarf_P_Die die, Dwarf_Half attr,
+    Dwarf_Signed value, Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+
+	if (dbg == NULL || die == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_BADADDR);
+	}
+
+	if (_dwarf_attr_alloc(die, &at, error) != DW_DLE_NONE)
+		return (DW_DLV_BADADDR);
+
+	at->at_die = die;
+	at->at_attrib = attr;
+	at->u[0].u64 = value;
+
+	if (value >= SCHAR_MIN && value <= SCHAR_MAX)
+		at->at_form = DW_FORM_data1;
+	else if (value >= SHRT_MIN && value <= SHRT_MAX)
+		at->at_form = DW_FORM_data2;
+	else if (value >= INT_MIN && value <= INT_MAX)
+		at->at_form = DW_FORM_data4;
+	else
+		at->at_form = DW_FORM_data8;
+
+	STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
+
+	return (at);
+}
+
+Dwarf_P_Attribute
+dwarf_add_AT_reference(Dwarf_P_Debug dbg, Dwarf_P_Die die, Dwarf_Half attr,
+    Dwarf_P_Die ref_die, Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+
+	if (dbg == NULL || die == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_BADADDR);
+	}
+
+	if (_dwarf_attr_alloc(die, &at, error) != DW_DLE_NONE)
+		return (DW_DLV_BADADDR);
+
+	at->at_die = die;
+	at->at_attrib = attr;
+	if (dbg->dbg_offset_size == 4)
+		at->at_form = DW_FORM_ref4;
+	else
+		at->at_form = DW_FORM_ref8;
+
+	at->at_refdie = ref_die;
+
+	STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
+
+	return (at);
+}
+
+Dwarf_P_Attribute
+dwarf_add_AT_flag(Dwarf_P_Debug dbg, Dwarf_P_Die die, Dwarf_Half attr,
+    Dwarf_Small flag, Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+
+	if (dbg == NULL || die == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_BADADDR);
+	}
+
+	if (_dwarf_attr_alloc(die, &at, error) != DW_DLE_NONE)
+		return (DW_DLV_BADADDR);
+
+	at->at_die = die;
+	at->at_attrib = attr;
+	at->at_form = DW_FORM_flag;
+	at->u[0].u64 = flag ? 1 : 0;
+
+	STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
+
+	return (at);
+}
+
+Dwarf_P_Attribute
+dwarf_add_AT_string(Dwarf_P_Debug dbg, Dwarf_P_Die die, Dwarf_Half attr,
+    char *string, Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+
+	if (dbg == NULL || die == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_BADADDR);
+	}
+
+	/* XXX Add DW_FORM_string style string instead? */
+
+	if (_dwarf_add_string_attr(die, &at, attr, string, error) !=
+	    DW_DLE_NONE)
+		return (DW_DLV_BADADDR);
+
+	return (at);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_pro_die.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,110 @@
+/*-
+ * Copyright (c) 2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_pro_die.c 2074 2011-10-27 03:34:33Z jkoshy $");
+
+Dwarf_Unsigned
+dwarf_add_die_to_debug(Dwarf_P_Debug dbg, Dwarf_P_Die first_die,
+    Dwarf_Error *error)
+{
+
+	if (dbg == NULL || first_die == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_NOCOUNT);
+	}
+
+	dbg->dbgp_root_die = first_die;
+
+	return (DW_DLV_OK);
+}
+
+Dwarf_P_Die
+dwarf_new_die(Dwarf_P_Debug dbg, Dwarf_Tag new_tag,
+    Dwarf_P_Die parent, Dwarf_P_Die child, Dwarf_P_Die left_sibling,
+    Dwarf_P_Die right_sibling, Dwarf_Error *error)
+{
+	Dwarf_P_Die die;
+	int count;
+
+	if (dbg == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_BADADDR);
+	}
+
+	count = _dwarf_die_count_links(parent, child, left_sibling,
+	    right_sibling);
+
+	if (count > 1) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_BADADDR);
+	}
+
+	if (_dwarf_die_alloc(dbg, &die, error) != DW_DLE_NONE)
+		return (DW_DLV_BADADDR);
+
+	die->die_dbg = dbg;
+	die->die_tag = new_tag;
+
+	STAILQ_INSERT_TAIL(&dbg->dbgp_dielist, die, die_pro_next);
+
+	if (count == 0)
+		return (die);
+
+	_dwarf_die_link(die, parent, child, left_sibling, right_sibling);
+
+	return (die);
+}
+
+Dwarf_P_Die
+dwarf_die_link(Dwarf_P_Die die, Dwarf_P_Die parent,
+    Dwarf_P_Die child, Dwarf_P_Die left_sibling, Dwarf_P_Die right_sibling,
+    Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+	int count;
+
+
+	if (die == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_BADADDR);
+	}
+
+	dbg = die->die_dbg;
+	count = _dwarf_die_count_links(parent, child, left_sibling,
+	    right_sibling);
+
+	if (count > 1) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_BADADDR);
+	} else if (count == 0)
+		return (die);
+
+	_dwarf_die_link(die, parent, child, left_sibling, right_sibling);
+
+	return (die);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_pro_expr.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,223 @@
+/*-
+ * Copyright (c) 2010 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_pro_expr.c 2074 2011-10-27 03:34:33Z jkoshy $");
+
+static struct _Dwarf_P_Expr_Entry *
+_dwarf_add_expr(Dwarf_P_Expr expr, Dwarf_Small opcode, Dwarf_Unsigned val1,
+    Dwarf_Unsigned val2, Dwarf_Error *error)
+{
+	struct _Dwarf_P_Expr_Entry *ee;
+	Dwarf_Debug dbg;
+	int len;
+
+	dbg = expr != NULL ? expr->pe_dbg : NULL;
+
+	if (_dwarf_loc_expr_add_atom(expr->pe_dbg, NULL, NULL, opcode, val1,
+	    val2, &len, error) != DW_DLE_NONE)
+		return (NULL);
+	assert(len > 0);
+
+	if ((ee = calloc(1, sizeof(*ee))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (NULL);
+	}
+
+	STAILQ_INSERT_TAIL(&expr->pe_eelist, ee, ee_next);
+
+	ee->ee_loc.lr_atom = opcode;
+	ee->ee_loc.lr_number = val1;
+	ee->ee_loc.lr_number2 = val2;
+	ee->ee_loc.lr_offset = expr->pe_length;
+	expr->pe_length += len;
+	expr->pe_invalid = 1;
+
+	return (ee);
+}
+
+int
+_dwarf_expr_into_block(Dwarf_P_Expr expr, Dwarf_Error *error)
+{
+	struct _Dwarf_P_Expr_Entry *ee;
+	Dwarf_Debug dbg;
+	int len, pos, ret;
+
+	dbg = expr != NULL ? expr->pe_dbg : NULL;
+
+	if (expr->pe_block != NULL) {
+		free(expr->pe_block);
+		expr->pe_block = NULL;
+	}
+
+	if (expr->pe_length <= 0) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_EXPR_LENGTH_BAD);
+		return (DW_DLE_EXPR_LENGTH_BAD);
+	}
+
+
+	if ((expr->pe_block = calloc((size_t) expr->pe_length, 1)) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+
+	pos = 0;
+	STAILQ_FOREACH(ee, &expr->pe_eelist, ee_next) {
+		assert((Dwarf_Unsigned) pos < expr->pe_length);
+		ret = _dwarf_loc_expr_add_atom(expr->pe_dbg,
+		    &expr->pe_block[pos], &expr->pe_block[expr->pe_length],
+		    ee->ee_loc.lr_atom, ee->ee_loc.lr_number,
+		    ee->ee_loc.lr_number2, &len, error);
+		assert(ret == DW_DLE_NONE);
+		assert(len > 0);
+		pos += len;
+	}
+
+	expr->pe_invalid = 0;
+
+	return (DW_DLE_NONE);
+}
+
+void
+_dwarf_expr_cleanup(Dwarf_P_Debug dbg)
+{
+	Dwarf_P_Expr pe, tpe;
+	struct _Dwarf_P_Expr_Entry *ee, *tee;
+
+	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
+
+	STAILQ_FOREACH_SAFE(pe, &dbg->dbgp_pelist, pe_next, tpe) {
+		STAILQ_REMOVE(&dbg->dbgp_pelist, pe, _Dwarf_P_Expr, pe_next);
+		STAILQ_FOREACH_SAFE(ee, &pe->pe_eelist, ee_next, tee) {
+			STAILQ_REMOVE(&pe->pe_eelist, ee, _Dwarf_P_Expr_Entry,
+			    ee_next);
+			free(ee);
+		}
+		if (pe->pe_block)
+			free(pe->pe_block);
+		free(pe);
+	}
+}
+
+Dwarf_P_Expr
+dwarf_new_expr(Dwarf_P_Debug dbg, Dwarf_Error *error)
+{
+	Dwarf_P_Expr pe;
+
+	if (dbg == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_BADADDR);
+	}
+
+	if ((pe = calloc(1, sizeof(struct _Dwarf_P_Expr))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLV_BADADDR);
+	}
+	STAILQ_INIT(&pe->pe_eelist);
+
+	STAILQ_INSERT_TAIL(&dbg->dbgp_pelist, pe, pe_next);
+	pe->pe_dbg = dbg;
+
+	return (pe);
+}
+
+Dwarf_Unsigned
+dwarf_add_expr_gen(Dwarf_P_Expr expr, Dwarf_Small opcode, Dwarf_Unsigned val1,
+    Dwarf_Unsigned val2, Dwarf_Error *error)
+{
+
+	if (expr == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_NOCOUNT);
+	}
+
+	if (_dwarf_add_expr(expr, opcode, val1, val2, error) == NULL)
+		return (DW_DLV_NOCOUNT);
+
+	return (expr->pe_length);
+}
+
+Dwarf_Unsigned
+dwarf_add_expr_addr(Dwarf_P_Expr expr, Dwarf_Unsigned address,
+    Dwarf_Signed sym_index, Dwarf_Error *error)
+{
+
+	return (dwarf_add_expr_addr_b(expr, address, sym_index, error));
+}
+
+Dwarf_Unsigned
+dwarf_add_expr_addr_b(Dwarf_P_Expr expr, Dwarf_Unsigned address,
+    Dwarf_Unsigned sym_index, Dwarf_Error *error)
+{
+	struct _Dwarf_P_Expr_Entry *ee;
+
+	if (expr == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_NOCOUNT);
+	}
+
+	if ((ee = _dwarf_add_expr(expr, DW_OP_addr, address, 0, error)) == NULL)
+		return (DW_DLV_NOCOUNT);
+
+	ee->ee_sym = sym_index;
+
+	return (expr->pe_length);
+}
+
+Dwarf_Unsigned
+dwarf_expr_current_offset(Dwarf_P_Expr expr, Dwarf_Error *error)
+{
+
+	if (expr == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_NOCOUNT);
+	}
+
+	return (expr->pe_length);
+}
+
+Dwarf_Addr
+dwarf_expr_into_block(Dwarf_P_Expr expr, Dwarf_Unsigned *length,
+    Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+
+	dbg = expr != NULL ? expr->pe_dbg : NULL;
+
+	if (expr == NULL || length == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return ((Dwarf_Addr) (uintptr_t) DW_DLV_BADADDR);
+	}
+
+	if (expr->pe_block == NULL || expr->pe_invalid)
+		if (_dwarf_expr_into_block(expr, error) != DW_DLE_NONE)
+			return ((Dwarf_Addr) (uintptr_t) DW_DLV_BADADDR);
+
+	*length = expr->pe_length;
+
+	return ((Dwarf_Addr) (uintptr_t) expr->pe_block);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_pro_finish.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 2010 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_pro_finish.c 2074 2011-10-27 03:34:33Z jkoshy $");
+
+Dwarf_Unsigned
+dwarf_producer_finish(Dwarf_P_Debug dbg, Dwarf_Error *error)
+{
+
+	if (dbg == NULL || dbg->dbg_mode != DW_DLC_WRITE) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_NOCOUNT);
+	}
+
+	_dwarf_deinit(dbg);
+
+	free(dbg);
+
+	return (1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_pro_frame.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,195 @@
+/*-
+ * Copyright (c) 2010 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_pro_frame.c 2074 2011-10-27 03:34:33Z jkoshy $");
+
+Dwarf_P_Fde
+dwarf_new_fde(Dwarf_P_Debug dbg, Dwarf_Error *error)
+{
+	Dwarf_P_Fde fde;
+
+	if (dbg == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_BADADDR);
+	}
+
+	if ((fde = calloc(1, sizeof(struct _Dwarf_Fde))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLV_BADADDR);
+	}
+
+	fde->fde_dbg = dbg;
+
+	return (fde);
+}
+
+Dwarf_Unsigned
+dwarf_add_frame_cie(Dwarf_P_Debug dbg, char *augmenter, Dwarf_Small caf,
+    Dwarf_Small daf, Dwarf_Small ra, Dwarf_Ptr initinst,
+    Dwarf_Unsigned inst_len, Dwarf_Error *error)
+{
+	Dwarf_P_Cie cie;
+
+	if (dbg == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_NOCOUNT);
+	}
+
+	if ((cie = calloc(1, sizeof(struct _Dwarf_Cie))) == NULL) {
+		DWARF_SET_ERROR(dbg, error,DW_DLE_MEMORY);
+		return (DW_DLV_NOCOUNT);
+	}
+	STAILQ_INSERT_TAIL(&dbg->dbgp_cielist, cie, cie_next);
+
+	cie->cie_index = dbg->dbgp_cielen++;
+
+	if (augmenter != NULL) {
+		cie->cie_augment = (uint8_t *) strdup(augmenter);
+		if (cie->cie_augment == NULL) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+			return (DW_DLV_NOCOUNT);
+		}
+	}
+
+	cie->cie_caf = caf;
+	cie->cie_daf = (int8_t) daf; /* daf is signed. */
+	cie->cie_ra = ra;
+	if (initinst != NULL && inst_len > 0) {
+		cie->cie_initinst = malloc((size_t) inst_len);
+		if (cie->cie_initinst == NULL) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+			return (DW_DLV_NOCOUNT);
+		}
+		memcpy(cie->cie_initinst, initinst, inst_len);
+		cie->cie_instlen = inst_len;
+	}
+
+	return (cie->cie_index);
+}
+
+Dwarf_Unsigned
+dwarf_add_frame_fde(Dwarf_P_Debug dbg, Dwarf_P_Fde fde, Dwarf_P_Die die,
+    Dwarf_Unsigned cie, Dwarf_Addr virt_addr, Dwarf_Unsigned code_len,
+    Dwarf_Unsigned symbol_index, Dwarf_Error *error)
+{
+
+	return (dwarf_add_frame_fde_b(dbg, fde, die, cie, virt_addr, code_len,
+	    symbol_index, 0, 0, error));
+}
+
+Dwarf_Unsigned
+dwarf_add_frame_fde_b(Dwarf_P_Debug dbg, Dwarf_P_Fde fde, Dwarf_P_Die die,
+    Dwarf_Unsigned cie, Dwarf_Addr virt_addr, Dwarf_Unsigned code_len,
+    Dwarf_Unsigned symbol_index, Dwarf_Unsigned end_symbol_index,
+    Dwarf_Addr offset_from_end_sym, Dwarf_Error *error)
+{
+	Dwarf_P_Cie ciep;
+	int i;
+
+	/*
+	 * XXX SGI libdwarf need the DIE arg because later it will insert a
+	 * DW_AT_MIPS_fde attribute, which points to the offset the
+	 * correspoding FDE, into this DIE. Do we need this?
+	 */
+	(void) die;
+
+	if (dbg == NULL || fde == NULL || fde->fde_dbg != dbg) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_NOCOUNT);
+	}
+
+	ciep = STAILQ_FIRST(&dbg->dbgp_cielist);
+	for (i = 0; (Dwarf_Unsigned) i < cie; i++) {
+		ciep = STAILQ_NEXT(ciep, cie_next);
+		if (ciep == NULL)
+			break;
+	}
+	if (ciep == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_NOCOUNT);
+	}
+
+	if (end_symbol_index > 0 &&
+	    (dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) == 0) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_NOCOUNT);
+	}
+
+	fde->fde_cie = ciep;
+	fde->fde_initloc = virt_addr;
+	fde->fde_adrange = code_len;
+	fde->fde_symndx = symbol_index;
+	fde->fde_esymndx = end_symbol_index;
+	fde->fde_eoff = offset_from_end_sym;
+
+	STAILQ_INSERT_TAIL(&dbg->dbgp_fdelist, fde, fde_next);
+
+	return (dbg->dbgp_fdelen++);
+}
+
+Dwarf_P_Fde
+dwarf_fde_cfa_offset(Dwarf_P_Fde fde, Dwarf_Unsigned reg, Dwarf_Signed offset,
+    Dwarf_Error *error)
+{
+	int ret;
+	Dwarf_Debug dbg;
+
+	dbg = fde != NULL ? fde->fde_dbg : NULL;
+
+	if (fde == NULL || reg > 0x3f) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_BADADDR);
+	}
+
+	ret = _dwarf_frame_fde_add_inst(fde, DW_CFA_offset | (reg & 0x3f),
+	    offset, 0, error);
+
+	if (ret != DW_DLE_NONE)
+		return (DW_DLV_BADADDR);
+
+	return (fde);
+}
+
+Dwarf_P_Fde
+dwarf_add_fde_inst(Dwarf_P_Fde fde, Dwarf_Small op, Dwarf_Unsigned val1,
+    Dwarf_Unsigned val2, Dwarf_Error *error)
+{
+	int ret;
+
+	if (fde == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_BADADDR);
+	}
+
+	ret = _dwarf_frame_fde_add_inst(fde, op, val1, val2, error);
+
+	if (ret != DW_DLE_NONE)
+		return (DW_DLV_BADADDR);
+
+	return (fde);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_pro_funcs.m4	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2010 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_pro_funcs.m4 2074 2011-10-27 03:34:33Z jkoshy $");
+
+/* WARNING: GENERATED FROM __file__. */
+
+divert(-1)
+include(SRCDIR`/dwarf_pro_nametbl.m4')
+divert(0)
+MAKE_NAMETBL_PRO_API(func)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_pro_init.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,122 @@
+/*-
+ * Copyright (c) 2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_pro_init.c 2074 2011-10-27 03:34:33Z jkoshy $");
+
+Dwarf_P_Debug
+dwarf_producer_init(Dwarf_Unsigned flags, Dwarf_Callback_Func func,
+    Dwarf_Handler errhand, Dwarf_Ptr errarg, Dwarf_Error *error)
+{
+	Dwarf_P_Debug dbg;
+	int mode;
+
+	if (flags & DW_DLC_READ || flags & DW_DLC_RDWR) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_BADADDR);
+	}
+
+	if (flags & DW_DLC_WRITE)
+		mode = DW_DLC_WRITE;
+	else {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_BADADDR);
+	}
+
+	if (func == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_BADADDR);
+	}
+
+	if (_dwarf_alloc(&dbg, DW_DLC_WRITE, error) != DW_DLE_NONE)
+		return (DW_DLV_BADADDR);
+
+	dbg->dbg_mode = mode;
+
+	if (_dwarf_init(dbg, flags, errhand, errarg, error) != DW_DLE_NONE) {
+		free(dbg);
+		return (DW_DLV_BADADDR);
+	}
+
+	dbg->dbgp_func = func;
+
+	return (dbg);
+}
+
+Dwarf_P_Debug
+dwarf_producer_init_b(Dwarf_Unsigned flags, Dwarf_Callback_Func_b func,
+    Dwarf_Handler errhand, Dwarf_Ptr errarg, Dwarf_Error *error)
+{
+	Dwarf_P_Debug dbg;
+	int mode;
+
+	if (flags & DW_DLC_READ || flags & DW_DLC_RDWR) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_BADADDR);
+	}
+
+	if (flags & DW_DLC_WRITE)
+		mode = DW_DLC_WRITE;
+	else {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_BADADDR);
+	}
+
+	if (func == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_BADADDR);
+	}
+
+	if (_dwarf_alloc(&dbg, DW_DLC_WRITE, error) != DW_DLE_NONE)
+		return (DW_DLV_BADADDR);
+
+	dbg->dbg_mode = mode;
+
+	if (_dwarf_init(dbg, flags, errhand, errarg, error) != DW_DLE_NONE) {
+		free(dbg);
+		return (DW_DLV_BADADDR);
+	}
+
+	dbg->dbgp_func_b = func;
+
+	return (dbg);
+}
+
+int
+dwarf_producer_set_isa(Dwarf_P_Debug dbg, enum Dwarf_ISA isa,
+    Dwarf_Error *error)
+{
+
+	if (dbg == NULL || isa >= DW_ISA_MAX) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	dbg->dbgp_isa = isa;
+
+	return (DW_DLV_OK);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_pro_lineno.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,187 @@
+/*-
+ * Copyright (c) 2010 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_pro_lineno.c 2973 2013-12-23 06:46:16Z kaiwang27 $");
+
+Dwarf_Unsigned
+dwarf_add_line_entry(Dwarf_P_Debug dbg, Dwarf_Unsigned file,
+    Dwarf_Addr off, Dwarf_Unsigned lineno, Dwarf_Signed column,
+    Dwarf_Bool is_stmt, Dwarf_Bool basic_block, Dwarf_Error *error)
+{
+	Dwarf_LineInfo li;
+	Dwarf_Line ln;
+
+	if (dbg == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_NOCOUNT);
+	}
+
+	li = dbg->dbgp_lineinfo;
+
+	ln = STAILQ_LAST(&li->li_lnlist, _Dwarf_Line, ln_next);
+
+	if (ln == NULL || ln->ln_addr > off) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_NOCOUNT);
+	}
+
+	if ((ln = calloc(1, sizeof(struct _Dwarf_Line))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLV_NOCOUNT);
+	}
+	ln->ln_li     = li;
+	ln->ln_addr   = off;
+	ln->ln_symndx = 0;
+	ln->ln_fileno = file;
+	ln->ln_lineno = lineno;
+	ln->ln_column = column;
+	ln->ln_bblock = basic_block != 0;
+	ln->ln_stmt   = is_stmt != 0;
+	ln->ln_endseq = 0;
+	STAILQ_INSERT_TAIL(&li->li_lnlist, ln, ln_next);
+	li->li_lnlen++;
+
+	return (DW_DLV_OK);
+}
+
+Dwarf_Unsigned
+dwarf_lne_set_address(Dwarf_P_Debug dbg, Dwarf_Addr offs, Dwarf_Unsigned symndx,
+    Dwarf_Error *error)
+{
+	Dwarf_LineInfo li;
+	Dwarf_Line ln;
+
+	if (dbg == NULL || symndx == 0) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_NOCOUNT);
+	}
+
+	li = dbg->dbgp_lineinfo;
+
+	if ((ln = calloc(1, sizeof(struct _Dwarf_Line))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLV_NOCOUNT);
+	}
+	ln->ln_li = li;
+	ln->ln_addr = offs;
+	ln->ln_symndx = symndx;
+	STAILQ_INSERT_TAIL(&li->li_lnlist, ln, ln_next);
+	li->li_lnlen++;
+
+	return (DW_DLV_OK);
+}
+
+Dwarf_Unsigned
+dwarf_lne_end_sequence(Dwarf_P_Debug dbg, Dwarf_Addr addr, Dwarf_Error *error)
+{
+	Dwarf_LineInfo li;
+	Dwarf_Line ln;
+
+	if (dbg == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_NOCOUNT);
+	}
+
+	li = dbg->dbgp_lineinfo;
+
+	ln = STAILQ_LAST(&li->li_lnlist, _Dwarf_Line, ln_next);
+	if (ln && ln->ln_addr >= addr) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_NOCOUNT);
+	}
+
+	if ((ln = calloc(1, sizeof(struct _Dwarf_Line))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLV_NOCOUNT);
+	}
+	ln->ln_li = li;
+	ln->ln_addr = addr;
+	ln->ln_endseq = 1;
+	STAILQ_INSERT_TAIL(&li->li_lnlist, ln, ln_next);
+	li->li_lnlen++;
+
+	return (DW_DLV_OK);
+}
+
+Dwarf_Unsigned
+dwarf_add_directory_decl(Dwarf_P_Debug dbg, char *name, Dwarf_Error *error)
+{
+	Dwarf_LineInfo li;
+
+	if (dbg == NULL || name == NULL || strlen(name) == 0) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_NOCOUNT);
+	}
+
+	li = dbg->dbgp_lineinfo;
+
+	li->li_incdirs = realloc(li->li_incdirs, (li->li_inclen + 1) *
+	    sizeof(char *));
+	if (li->li_incdirs == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLV_NOCOUNT);
+	}
+	if ((li->li_incdirs[li->li_inclen] = strdup(name)) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLV_NOCOUNT);
+	}
+
+	return (++li->li_inclen);
+}
+
+Dwarf_Unsigned
+dwarf_add_file_decl(Dwarf_P_Debug dbg, char *name, Dwarf_Unsigned dirndx,
+    Dwarf_Unsigned mtime, Dwarf_Unsigned size, Dwarf_Error *error)
+{
+	Dwarf_LineInfo li;
+	Dwarf_LineFile lf;
+
+	if (dbg == NULL || name == NULL || strlen(name) == 0) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_NOCOUNT);
+	}
+
+	li = dbg->dbgp_lineinfo;
+
+	if ((lf = malloc(sizeof(struct _Dwarf_LineFile))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+
+	if ((lf->lf_fname = strdup(name)) == NULL) {
+		free(lf);
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+	lf->lf_dirndx = dirndx;
+	lf->lf_mtime = mtime;
+	lf->lf_size = size;
+	STAILQ_INSERT_TAIL(&li->li_lflist, lf, lf_next);
+
+	return (++li->li_lflen);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_pro_macinfo.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,142 @@
+/*-
+ * Copyright (c) 2010 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_pro_macinfo.c 2074 2011-10-27 03:34:33Z jkoshy $");
+
+static int
+_dwarf_add_macro(Dwarf_P_Debug dbg, int type, Dwarf_Unsigned lineno,
+    Dwarf_Signed fileindex, char *str1, char *str2, Dwarf_Error *error)
+{
+	Dwarf_Macro_Details *md;
+	int len;
+
+	dbg->dbgp_mdlist = realloc(dbg->dbgp_mdlist,
+	    (size_t) dbg->dbgp_mdcnt + 1);
+	if (dbg->dbgp_mdlist == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLV_ERROR);
+	}
+
+	md = &dbg->dbgp_mdlist[dbg->dbgp_mdcnt];
+	dbg->dbgp_mdcnt++;
+
+	md->dmd_offset = 0;
+	md->dmd_type = type;
+	md->dmd_lineno = lineno;
+	md->dmd_fileindex = fileindex;
+	md->dmd_macro = NULL;
+
+	if (str1 == NULL)
+		return (DW_DLV_OK);
+	else if (str2 == NULL) {
+		if ((md->dmd_macro = strdup(str1)) == NULL) {
+			dbg->dbgp_mdcnt--;
+			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+			return (DW_DLV_ERROR);
+		}
+		return (DW_DLV_OK);
+	} else {
+		len = strlen(str1) + strlen(str2) + 2;
+		if ((md->dmd_macro = malloc(len)) == NULL) {
+			dbg->dbgp_mdcnt--;
+			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+			return (DW_DLV_ERROR);
+		}
+		snprintf(md->dmd_macro, len, "%s %s", str1, str2);
+		return (DW_DLV_OK);
+	}
+}
+
+int
+dwarf_def_macro(Dwarf_P_Debug dbg, Dwarf_Unsigned lineno, char *name,
+    char *value, Dwarf_Error *error)
+{
+
+	if (dbg == NULL || name == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	return (_dwarf_add_macro(dbg, DW_MACINFO_define, lineno, -1, name,
+	    value, error));
+}
+
+int
+dwarf_undef_macro(Dwarf_P_Debug dbg, Dwarf_Unsigned lineno, char *name,
+    Dwarf_Error *error)
+{
+
+	if (dbg == NULL || name == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	return (_dwarf_add_macro(dbg, DW_MACINFO_undef, lineno, -1, name,
+	    NULL, error));
+}
+
+int
+dwarf_start_macro_file(Dwarf_P_Debug dbg, Dwarf_Unsigned lineno,
+    Dwarf_Unsigned fileindex, Dwarf_Error *error)
+{
+
+	if (dbg == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	return (_dwarf_add_macro(dbg, DW_MACINFO_start_file, lineno, fileindex,
+	    NULL, NULL, error));
+}
+
+int
+dwarf_end_macro_file(Dwarf_P_Debug dbg, Dwarf_Error *error)
+{
+
+	if (dbg == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	return (_dwarf_add_macro(dbg, DW_MACINFO_end_file, 0, -1,
+	    NULL, NULL, error));
+}
+
+int
+dwarf_vendor_ext(Dwarf_P_Debug dbg, Dwarf_Unsigned constant, char *string,
+    Dwarf_Error *error)
+{
+
+	if (dbg == NULL || string == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	return (_dwarf_add_macro(dbg, DW_MACINFO_vendor_ext, constant, -1,
+	    string, NULL, error));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_pro_nametbl.m4	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,70 @@
+/*-
+ * Copyright (c) 2010 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: dwarf_pro_nametbl.m4 2074 2011-10-27 03:34:33Z jkoshy $
+ */
+
+define(`MAKE_NAMETBL_PRO_API',`
+Dwarf_Unsigned
+dwarf_add_$1name(Dwarf_P_Debug dbg, Dwarf_P_Die die, char *$1_name,
+    Dwarf_Error *error)
+{
+	Dwarf_NameTbl nt;
+	Dwarf_NamePair np;
+
+	if (dbg == NULL || die == NULL || $1_name == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (0);
+	}
+
+	if (dbg->dbgp_$1s == NULL) {
+		dbg->dbgp_$1s = calloc(1, sizeof(struct _Dwarf_NameTbl));
+		if (dbg->dbgp_$1s == NULL) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+			return (0);
+		}
+		STAILQ_INIT(&dbg->dbgp_$1s->nt_nplist);
+	}
+
+	nt = dbg->dbgp_$1s;
+
+	if ((np = calloc(1, sizeof(struct _Dwarf_NamePair))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (0);
+	}
+
+	np->np_nt = nt;
+	np->np_die = die;
+	if ((np->np_name = strdup($1_name)) == NULL) {
+		free(np);
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (0);
+	}
+
+	STAILQ_INSERT_TAIL(&nt->nt_nplist, np, np_next);
+
+	return (1);
+}
+')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_pro_pubnames.m4	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2010 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_pro_pubnames.m4 2074 2011-10-27 03:34:33Z jkoshy $");
+
+/* WARNING: GENERATED FROM __file__. */
+
+divert(-1)
+include(SRCDIR`/dwarf_pro_nametbl.m4')
+divert(0)
+MAKE_NAMETBL_PRO_API(pub)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_pro_reloc.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,114 @@
+/*-
+ * Copyright (c) 2010 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_pro_reloc.c 2074 2011-10-27 03:34:33Z jkoshy $");
+
+int
+dwarf_get_relocation_info_count(Dwarf_P_Debug dbg, Dwarf_Unsigned *reloc_cnt,
+    int *drd_buffer_version, Dwarf_Error *error)
+{
+
+	if (dbg == NULL || reloc_cnt == NULL || drd_buffer_version == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if ((dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) == 0) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	*reloc_cnt = dbg->dbgp_drscnt;
+	*drd_buffer_version = DWARF_DRD_BUFFER_VERSION;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_relocation_info(Dwarf_P_Debug dbg, Dwarf_Signed *elf_section_index,
+    Dwarf_Signed *elf_section_link, Dwarf_Unsigned *reloc_entry_count,
+    Dwarf_Relocation_Data *reloc_buffer, Dwarf_Error *error)
+{
+	Dwarf_Rel_Section drs;
+	Dwarf_Rel_Entry dre;
+	int i;
+
+	if (dbg == NULL || elf_section_index == NULL ||
+	    elf_section_link == NULL || reloc_entry_count == NULL ||
+	    reloc_buffer == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if ((dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) == 0) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	if (dbg->dbgp_drscnt == 0) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	if (dbg->dbgp_drspos == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	drs = dbg->dbgp_drspos;
+	assert(drs->drs_ds != NULL && drs->drs_ref != NULL);
+	assert(drs->drs_drecnt > 0);
+
+	*elf_section_index = drs->drs_ds->ds_ndx;
+	*elf_section_link = drs->drs_ref->ds_ndx;
+	*reloc_entry_count = drs->drs_drecnt;
+
+	if (drs->drs_drd == NULL) {
+		drs->drs_drd = calloc(*reloc_entry_count,
+		    sizeof(struct Dwarf_Relocation_Data_s));
+		if (drs->drs_drd == NULL) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+			return (DW_DLV_ERROR);
+		}
+		for (i = 0, dre = STAILQ_FIRST(&drs->drs_dre);
+		    (Dwarf_Unsigned) i < *reloc_entry_count && dre != NULL;
+		    i++, dre = STAILQ_NEXT(dre, dre_next)) {
+			drs->drs_drd[i].drd_type = dre->dre_type;
+			drs->drs_drd[i].drd_length = dre->dre_length;
+			drs->drs_drd[i].drd_offset = dre->dre_offset;
+			drs->drs_drd[i].drd_symbol_index = dre->dre_symndx;
+		}
+		assert((Dwarf_Unsigned) i == *reloc_entry_count && dre == NULL);
+	}
+
+	*reloc_buffer = drs->drs_drd;
+
+	dbg->dbgp_drspos = STAILQ_NEXT(dbg->dbgp_drspos, drs_next);
+
+	return (DW_DLV_OK);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_pro_sections.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,81 @@
+/*-
+ * Copyright (c) 2010 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_pro_sections.c 2074 2011-10-27 03:34:33Z jkoshy $");
+
+Dwarf_Signed
+dwarf_transform_to_disk_form(Dwarf_P_Debug dbg, Dwarf_Error *error)
+{
+
+	if (dbg == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_NOCOUNT);
+	}
+
+	if (_dwarf_generate_sections(dbg, error) != DW_DLE_NONE)
+		return (DW_DLV_NOCOUNT);
+
+	return (dbg->dbgp_seccnt);
+}
+
+Dwarf_Ptr
+dwarf_get_section_bytes(Dwarf_P_Debug dbg, Dwarf_Signed dwarf_section,
+    Dwarf_Signed *elf_section_index, Dwarf_Unsigned *length, Dwarf_Error *error)
+{
+	Dwarf_Ptr data;
+
+	(void) dwarf_section;	/* ignored. */
+
+	if (dbg == NULL || elf_section_index == NULL || length == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (NULL);
+	}
+
+	if (dbg->dbgp_secpos == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (NULL);
+	}
+
+	*elf_section_index = dbg->dbgp_secpos->ds_ndx;
+	*length = dbg->dbgp_secpos->ds_size;
+	data = dbg->dbgp_secpos->ds_data;
+
+	dbg->dbgp_secpos = STAILQ_NEXT(dbg->dbgp_secpos, ds_next);
+
+	return (data);
+}
+
+void
+dwarf_reset_section_bytes(Dwarf_P_Debug dbg)
+{
+
+	assert(dbg != NULL);
+
+	dbg->dbgp_secpos = STAILQ_FIRST(&dbg->dbgp_seclist);
+	dbg->dbgp_drspos = STAILQ_FIRST(&dbg->dbgp_drslist);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_pro_types.m4	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2010 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_pro_types.m4 2074 2011-10-27 03:34:33Z jkoshy $");
+
+/* WARNING: GENERATED FROM __file__. */
+
+divert(-1)
+include(SRCDIR`/dwarf_pro_nametbl.m4')
+divert(0)
+MAKE_NAMETBL_PRO_API(type)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_pro_vars.m4	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2010 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_pro_vars.m4 2074 2011-10-27 03:34:33Z jkoshy $");
+
+/* WARNING: GENERATED FROM __file__. */
+
+divert(-1)
+include(SRCDIR`/dwarf_pro_nametbl.m4')
+divert(0)
+MAKE_NAMETBL_PRO_API(var)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_pro_weaks.m4	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2010 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_pro_weaks.m4 2074 2011-10-27 03:34:33Z jkoshy $");
+
+/* WARNING: GENERATED FROM __file__. */
+
+divert(-1)
+include(SRCDIR`/dwarf_pro_nametbl.m4')
+divert(0)
+MAKE_NAMETBL_PRO_API(weak)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_producer_init.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,297 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_producer_init.3 3182 2015-04-10 16:08:10Z emaste $
+.\"
+.Dd August 20, 2011
+.Os
+.Dt DWARF_PRODUCER_INIT 3
+.Sh NAME
+.Nm dwarf_producer_init
+.Nm dwarf_producer_init_b
+.Nd allocate a DWARF producer descriptor
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft Dwarf_P_Debug
+.Fo dwarf_producer_init
+.Fa "Dwarf_Unsigned flags"
+.Fa "Dwarf_Callback_Func func"
+.Fa "Dwarf_Handler errhand"
+.Fa "Dwarf_Ptr errarg"
+.Fa "Dwarf_Error *err"
+.Fc
+.Ft Dwarf_P_Debug
+.Fo dwarf_producer_init_b
+.Fa "Dwarf_Unsigned flags"
+.Fa "Dwarf_Callback_Func_b func"
+.Fa "Dwarf_Handler errhand"
+.Fa "Dwarf_Ptr errarg"
+.Fa "Dwarf_Error *error"
+.Fc
+.Sh DESCRIPTION
+These functions allocate and return a
+.Vt Dwarf_P_Debug
+descriptor representing a DWARF producer instance.
+.Pp
+The argument
+.Ar errhand
+should contain the address of a function to be called in case of an
+error.
+If this argument is
+.Dv NULL ,
+the default error handling scheme is used, see
+.Xr dwarf 3 .
+.Pp
+The argument
+.Ar errarg
+will be passed to the error handler function when it is invoked.
+.Pp
+The argument
+.Ar err
+references a memory location that would hold a
+.Vt Dwarf_Error
+descriptor in case of an error.
+.Pp
+The argument
+.Ar flags
+specifies additional characteristics of the DWARF producer instance.
+The following flags are recognized:
+.Pp
+.Bl -tag -width "Dv DW_DLC_ISA_MIPS"
+.It Dv DW_DLC_ISA_IA64
+.Pq Deprecated
+The target instruction set architecture is IA64.
+This flag is deprecated.
+Application code should use the
+.Xr dwarf_producer_set_isa 3
+function to specify target instruction set architecture.
+.It Dv DW_DLC_ISA_MIPS
+.Pq Deprecated
+The target instruction set architecture is MIPS.
+This flag is deprecated.
+Application code should use the
+.Xr dwarf_producer_set_isa 3
+function to specify target instruction set architecture.
+.It Dv DW_DLC_SIZE_32
+.Pq Default
+The target address size is 32-bit.
+.It Dv DW_DLC_SIZE_64
+The target address size is 64-bit.
+.It Dv DW_DLC_STREAM_RELOCATIONS
+.Pq Default
+Generate stream relocations.
+.It Dv DW_DLC_SYMBOLIC_RELOCATIONS
+Generate symbolic relocations.
+.It Dv DW_DLC_TARGET_BIGENDIAN
+The target is big endian.
+.It Dv DW_DLC_TARGET_LITTLEENDIAN
+The target is little endian.
+.It Dv DW_DLC_WRITE
+.Pq Required
+Permit writing of DWARF information.
+.El
+.Pp
+The following flags are mutually exclusive.
+.Bl -bullet -compact
+.It
+Flags
+.Dv DW_DLC_ISA_IA64
+and
+.Dv DW_DLC_ISA_MIPS .
+.It
+Flags
+.Dv DW_DLC_SIZE_32
+and
+.Dv DW_DLC_SIZE_64 .
+.It
+Flags
+.Dv DW_DLC_STREAM_RELOCATIONS
+and
+.Dv DW_DLC_SYMBOLIC_RELOCATIONS .
+.It
+Flags
+.Dv DW_DLC_TARGET_BIGENDIAN
+and
+.Dv DW_DLC_TARGET_LITTLEENDIAN .
+.El
+If neither of the flags
+.Dv DW_DLC_TARGET_BIGENDIAN
+and
+.Dv DW_DLC_TARGET_LITTLEENDIAN
+is set, the target's endianness is assumed to be the same as the host's
+endianness.
+.Pp
+Argument
+.Ar func
+should point to an application-provided callback function of type
+.Vt Dwarf_Callback_Func_b .
+The type
+.Vt Dwarf_Callback_Func_b
+is defined in the header file
+.In libdwarf.h
+as:
+.Bd -literal -offset indent
+typedef int (*Dwarf_Callback_Func_b)(char *name, int size,
+    Dwarf_Unsigned type, Dwarf_Unsigned flags, Dwarf_Unsigned link,
+    Dwarf_Unsigned info, Dwarf_Unsigned *index, int *error);
+.Ed
+.Pp
+This function is called by the
+.Lb libdwarf
+once for each section in the object file that the library needs to
+create.
+The arguments to this callback function specify the values in the ELF
+section header for the section being created:
+.Pp
+.Bl -tag -width indent -compact -offset indent
+.It Ar name
+The name of the section being created.
+.It Ar size
+The
+.Va sh_size
+value in the section header.
+.It Ar type
+The
+.Va sh_type
+value in the section header.
+.It Ar flags
+The
+.Va sh_flags
+value in the section header.
+.It Ar link
+The
+.Va sh_link
+value in the section header.
+.It Ar info
+The
+.Va sh_info
+value in the section header.
+.El
+.Pp
+On success, the callback function should return the section index
+value of the created section, and set the location pointed to by
+argument
+.Ar index
+to the symbol table index of the symbol that associated with the newly
+created section.
+This symbol table index will be used in relocation entries
+referring to the created section.
+.Pp
+In case of failure, the callback function should return -1 and set the
+location pointed to by argument
+.Ar error
+to an application-defined error code.
+This application returned error code is currently ignored by the
+library.
+.Pp
+Function
+.Fn dwarf_producer_init
+is deprecated.
+Function
+.Fn dwarf_producer_init
+is identical to function
+.Fn dwarf_producer_init_b
+except that the callback function it expects can not properly handle
+arbitrary section symbol index values.
+.Ss Memory Management
+The
+.Vt Dwarf_P_Debug
+instance returned by these functions should be freed using the
+function
+.Fn dwarf_producer_finish .
+.Sh RETURN VALUES
+On success, these functions return the created DWARF producer
+descriptor.
+In case of an error, they return
+.Dv DW_DLV_BADADDR
+and set the argument
+.Ar err .
+.Sh ERRORS
+These functions can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_NO_ENTRY"
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Ar func
+was NULL.
+.It Bq Er DW_DLE_ARGUMENT
+The flag
+.Dv DW_DLC_WRITE
+was not set in argument
+.Ar flags .
+.It Bq Er DW_DLE_ARGUMENT
+The flags
+.Dv DW_DLC_SIZE_32
+and
+.Dv DW_DLC_SIZE_64
+were both set in argument
+.Ar flags .
+.It Bq Er DW_DLE_ARGUMENT
+The flags
+.Dv DW_DLC_ISA_IA64
+and
+.Dv DW_DLC_ISA_MIPS
+were both set in argument
+.Ar flags .
+.It Bq Er DW_DLE_ARGUMENT
+The flags
+.Dv DW_DLC_TARGET_BIGENDIAN
+and
+.Dv DW_DLC_TARGET_LITTLEENDIAN
+were both set in argument
+.Ar flags .
+.It Bq Er DW_DLE_ARGUMENT
+The flags
+.Dv DW_DLC_STREAM_RELOCATIONS
+and
+.Dv DW_DLC_SYMBOLIC_RELOCATIONS
+were both set in argument
+.Ar flags .
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered.
+.El
+.Sh EXAMPLES
+To initialize a
+.Vt Dwarf_P_Debug
+instance for a MIPS32 big endian object, use:
+.Bd -literal -offset indent
+Dwarf_P_Debug dbg;
+Dwarf_Unsigned flags;
+Dwarf_Error de;
+
+/* ... assume cb_func points to the callback function ... */
+
+flags = DW_DLC_WRITE | DW_DLC_SIZE_32 | DW_DLC_ISA_MIPS |
+    DW_DLC_STREAM_RELOCATIONS | DW_DLC_TARGET_BIGENDIAN;
+if ((dbg = dwarf_producer_init(flags, cb_func, NULL, NULL, &de)) ==
+    DW_DLV_BADADDR)
+	warnx("dwarf_producer_init failed: %s", dwarf_errmsg(-1));
+.Ed
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_errmsg 3 ,
+.Xr dwarf_producer_finish 3 ,
+.Xr dwarf_producer_set_isa 3 ,
+.Xr dwarf_transform_to_disk_form 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_producer_set_isa.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,98 @@
+.\" Copyright (c) 2011 Joseph Koshy
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_producer_set_isa.3 2074 2011-10-27 03:34:33Z jkoshy $
+.\"
+.Dd September 29, 2011
+.Os
+.Dt DWARF_PRODUCER_SET_ISA 3
+.Sh NAME
+.Nm dwarf_producer_set_isa
+.Nd specify the instruction set architecture for a DWARF producer instance
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_producer_set_isa
+.Fa "Dwarf_P_Debug dbg"
+.Fa "enum Dwarf_ISA isa"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+The function
+.Fn dwarf_producer_set_isa
+sets the instruction set architecture for a DWARF producer instance.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using one of
+the functions
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar isa
+specifies the desired instruction set architecture.
+Legal values for this argument are those defined by the
+.Vt "enum Dwarf_ISA"
+enumeration defined in the header file
+.In libdwarf.h .
+.Pp
+If the argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh COMPATIBILITY
+The
+.Fn dwarf_producer_set_isa
+function is a local extension.
+.Sh RETURN VALUES
+On success, the function
+.Fn dwarf_producer_set_isa
+returns
+.Dv DW_DLV_OK .
+In case of an error, this function returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+The
+.Fn dwarf_producer_set_isa
+function can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+The argument
+.Ar dbg
+was NULL.
+.It Bq Er DW_DLE_ARGUMENT
+The argument
+.Ar isa
+was invalid.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_pubnames.m4	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_pubnames.m4 2074 2011-10-27 03:34:33Z jkoshy $");
+
+/* WARNING: GENERATED FROM __file__. */
+
+divert(-1)
+include(SRCDIR`/dwarf_nametbl.m4')
+divert(0)
+MAKE_NAMETBL_API(global,Global,glob,pubnames)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_pubtypes.m4	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_pubtypes.m4 2074 2011-10-27 03:34:33Z jkoshy $");
+
+/* WARNING: GENERATED FROM __file__. */
+
+divert(-1)
+include(SRCDIR`/dwarf_nametbl.m4')
+divert(0)
+MAKE_NAMETBL_API(pubtype,Type,pubtype,pubtypes)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_ranges.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,87 @@
+/*-
+ * Copyright (c) 2009,2011 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_ranges.c 3029 2014-04-21 23:26:02Z kaiwang27 $");
+
+static int
+_dwarf_get_ranges(Dwarf_Debug dbg, Dwarf_CU cu, Dwarf_Off off,
+    Dwarf_Ranges **ranges, Dwarf_Signed *ret_cnt, Dwarf_Unsigned *ret_byte_cnt,
+    Dwarf_Error *error)
+{
+	Dwarf_Rangelist rl;
+	int ret;
+
+	assert(cu != NULL);
+	if (_dwarf_ranges_find(dbg, off, &rl) == DW_DLE_NO_ENTRY) {
+		ret = _dwarf_ranges_add(dbg, cu, off, &rl, error);
+		if (ret != DW_DLE_NONE)
+			return (DW_DLV_ERROR);
+	}
+
+	*ranges = rl->rl_rgarray;
+	*ret_cnt = rl->rl_rglen;
+
+	if (ret_byte_cnt != NULL)
+		*ret_byte_cnt = cu->cu_pointer_size * rl->rl_rglen * 2;
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_ranges(Dwarf_Debug dbg, Dwarf_Off offset, Dwarf_Ranges **ranges,
+    Dwarf_Signed *ret_cnt, Dwarf_Unsigned *ret_byte_cnt, Dwarf_Error *error)
+{
+
+	if (dbg == NULL || ranges == NULL || ret_cnt == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (!dbg->dbg_info_loaded) {
+		if (_dwarf_info_load(dbg, 1, 1, error) != DW_DLE_NONE)
+			return (DW_DLV_ERROR);
+	}
+
+	return (_dwarf_get_ranges(dbg, STAILQ_FIRST(&dbg->dbg_cu), offset,
+	    ranges, ret_cnt, ret_byte_cnt, error));
+}
+
+int
+dwarf_get_ranges_a(Dwarf_Debug dbg, Dwarf_Off offset, Dwarf_Die die,
+    Dwarf_Ranges **ranges, Dwarf_Signed *ret_cnt, Dwarf_Unsigned *ret_byte_cnt,
+    Dwarf_Error *error)
+{
+
+	if (dbg == NULL || die == NULL || ranges == NULL || ret_cnt == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	return (_dwarf_get_ranges(dbg, die->die_cu, offset, ranges, ret_cnt,
+	    ret_byte_cnt, error));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_reloc.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (c) 2010 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_reloc.c 3161 2015-02-15 21:43:36Z emaste $");
+
+int
+dwarf_set_reloc_application(int apply)
+{
+	int oldapply;
+
+	oldapply = _libdwarf.applyreloc;
+	_libdwarf.applyreloc = apply;
+
+	return (oldapply);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_reset_section_bytes.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,69 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_reset_section_bytes.3 2075 2011-10-27 03:47:28Z jkoshy $
+.\"
+.Dd September 3, 2011
+.Os
+.Dt DWARF_RESET_SECTION_BYTES 3
+.Sh NAME
+.Nm dwarf_reset_section_bytes
+.Nd reset the internal state of a producer instance
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft void
+.Fo dwarf_reset_section_bytes
+.Fa "Dwarf_P_Debug dbg"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_reset_section_bytes
+resets the internal state of a DWARF producer instance, so that the
+next call to the function
+.Xr dwarf_get_section_bytes 3
+will return the byte stream for the first generated section, and
+the next call to the function
+.Xr dwarf_get_relocation_info 3
+will return the first relocation array for the DWARF producer
+instance.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Sh RETURN VALUES
+Function
+.Fn dwarf_reset_section_bytes
+has no return value.
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_relocation_info 3 ,
+.Xr dwarf_get_section_bytes 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3 ,
+.Xr dwarf_transform_to_disk_form 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_sections.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,111 @@
+/*-
+ * Copyright (c) 2014 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_sections.c 3226 2015-06-23 13:00:16Z emaste $");
+
+#define	SET(N, V)				\
+	do {					\
+		if ((N) != NULL)		\
+			*(N) = (V);		\
+	} while (0)
+
+int
+dwarf_get_section_max_offsets_b(Dwarf_Debug dbg, Dwarf_Unsigned *debug_info,
+    Dwarf_Unsigned *debug_abbrev, Dwarf_Unsigned *debug_line,
+    Dwarf_Unsigned *debug_loc, Dwarf_Unsigned *debug_aranges,
+    Dwarf_Unsigned *debug_macinfo, Dwarf_Unsigned *debug_pubnames,
+    Dwarf_Unsigned *debug_str, Dwarf_Unsigned *debug_frame,
+    Dwarf_Unsigned *debug_ranges, Dwarf_Unsigned *debug_pubtypes,
+    Dwarf_Unsigned *debug_types)
+{
+	const char *n;
+	Dwarf_Unsigned sz;
+	int i;
+
+	if (dbg == NULL)
+		return (DW_DLV_ERROR);
+
+	SET(debug_info, 0);
+	SET(debug_abbrev, 0);
+	SET(debug_line, 0);
+	SET(debug_loc, 0);
+	SET(debug_aranges, 0);
+	SET(debug_macinfo, 0);
+	SET(debug_pubnames, 0);
+	SET(debug_str, 0);
+	SET(debug_frame, 0);
+	SET(debug_ranges, 0);
+	SET(debug_pubtypes, 0);
+	SET(debug_types, 0);
+
+	for (i = 0; (Dwarf_Unsigned) i < dbg->dbg_seccnt; i++) {
+		n = dbg->dbg_section[i].ds_name;
+		sz = dbg->dbg_section[i].ds_size;
+		if (!strcmp(n, ".debug_info"))
+			SET(debug_info, sz);
+		else if (!strcmp(n, ".debug_abbrev"))
+			SET(debug_abbrev, sz);
+		else if (!strcmp(n, ".debug_line"))
+			SET(debug_line, sz);
+		else if (!strcmp(n, ".debug_loc"))
+			SET(debug_loc, sz);
+		else if (!strcmp(n, ".debug_aranges"))
+			SET(debug_aranges, sz);
+		else if (!strcmp(n, ".debug_macinfo"))
+			SET(debug_macinfo, sz);
+		else if (!strcmp(n, ".debug_pubnames"))
+			SET(debug_pubnames, sz);
+		else if (!strcmp(n, ".debug_str"))
+			SET(debug_str, sz);
+		else if (!strcmp(n, ".debug_frame"))
+			SET(debug_frame, sz);
+		else if (!strcmp(n, ".debug_ranges"))
+			SET(debug_ranges, sz);
+		else if (!strcmp(n, ".debug_pubtypes"))
+			SET(debug_pubtypes, sz);
+		else if (!strcmp(n, ".debug_types"))
+			SET(debug_types, sz);
+	}
+
+	return (DW_DLV_OK);
+}
+
+int
+dwarf_get_section_max_offsets(Dwarf_Debug dbg, Dwarf_Unsigned *debug_info,
+    Dwarf_Unsigned *debug_abbrev, Dwarf_Unsigned *debug_line,
+    Dwarf_Unsigned *debug_loc, Dwarf_Unsigned *debug_aranges,
+    Dwarf_Unsigned *debug_macinfo, Dwarf_Unsigned *debug_pubnames,
+    Dwarf_Unsigned *debug_str, Dwarf_Unsigned *debug_frame,
+    Dwarf_Unsigned *debug_ranges, Dwarf_Unsigned *debug_pubtypes)
+{
+
+	return (dwarf_get_section_max_offsets_b(dbg, debug_info, debug_abbrev,
+	    debug_line, debug_loc, debug_aranges, debug_macinfo,
+	    debug_pubnames, debug_str, debug_frame, debug_ranges,
+	    debug_pubtypes, NULL));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_set_frame_cfa_value.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,140 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_set_frame_cfa_value.3 2075 2011-10-27 03:47:28Z jkoshy $
+.\"
+.Dd June 18, 2011
+.Os
+.Dt DWARF_SET_FRAME_CFA_VALUE 3
+.Sh NAME
+.Nm dwarf_set_frame_cfa_value ,
+.Nm dwarf_set_frame_rule_initial_value ,
+.Nm dwarf_set_frame_rule_table_size ,
+.Nm dwarf_set_frame_same_value ,
+.Nm dwarf_set_frame_undefined_value
+.Nd set internal register rule table parameters
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft Dwarf_Half
+.Fo dwarf_set_frame_cfa_value
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Half value"
+.Fc
+.Ft Dwarf_Half
+.Fo dwarf_set_frame_rule_initial_value
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Half value"
+.Fc
+.Ft Dwarf_Half
+.Fo dwarf_set_frame_rule_table_size
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Half value"
+.Fc
+.Ft Dwarf_Half
+.Fo dwarf_set_frame_same_value
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Half value"
+.Fc
+.Ft Dwarf_Half
+.Fo dwarf_set_frame_undefined_value
+.Fa "Dwarf_Debug dbg"
+.Fa "Dwarf_Half value"
+.Fc
+.Sh DESCRIPTION
+These functions set the parameters of the internal register
+rule table.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF debug context allocated using
+.Xr dwarf_init 3 .
+.Pp
+Argument
+.Ar value
+should hold the parameter value to set.
+.Pp
+Function
+.Fn dwarf_set_frame_cfa_value
+sets the column number for the CFA register rule in the internal
+register rule table.
+The constant
+.Dv DW_FRAME_CFA_COL
+is the default CFA register column number for DWARF2-only
+interfaces, and the constant
+.Dv DW_FRAME_CFA_COL3
+is the default CFA column number for DWARF3-compatible interfaces.
+.Pp
+Function
+.Fn dwarf_set_frame_rule_initial_value
+sets the initial value of the register rules in the internal register
+rule table.
+The default initial value is the constant
+.Dv DW_FRAME_REG_INITIAL_VALUE ,
+defined in the header file
+.In libdwarf.h .
+.Pp
+Function
+.Fn dwarf_set_frame_rule_table_size
+sets the maxmium number of columns of the internal register rule table.
+Argument
+.Ar value
+should be at least as large as the number of real registers in the ABI.
+.Pp
+Function
+.Fn dwarf_set_frame_same_value
+sets the register number representing the
+.Dq "same value"
+register rule.
+The default register number for the
+.Dq "same value"
+rule is the constant
+.Dv DW_FRAME_SAME_VAL ,
+defined in the header file
+.In libdwarf.h .
+.Pp
+Function
+.Fn dwarf_set_frame_undefined_value
+sets the register number representing the
+.Dq undefined
+register rule.
+The default register number for the
+.Dq undefined
+rule is the constant
+.Dv DW_FRAME_UNDEFINED_VAL ,
+defined in the header file
+.In libdwarf.h .
+.Sh RETURN VALUES
+These functions return the previous value of the parameter being
+set.
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_fde_at_pc 3 ,
+.Xr dwarf_get_fde_info_for_all_regs 3 ,
+.Xr dwarf_get_fde_info_for_all_regs3 3 ,
+.Xr dwarf_get_fde_info_for_cfa_reg3 3 ,
+.Xr dwarf_get_fde_info_for_reg 3 ,
+.Xr dwarf_get_fde_info_for_reg3 3 ,
+.Xr dwarf_get_fde_n 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_set_reloc_application.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,82 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_set_reloc_application.3 3161 2015-02-15 21:43:36Z emaste $
+.\"
+.Dd February 11, 2015
+.Os
+.Dt DWARF_SET_RELOC_APPLICATION 3
+.Sh NAME
+.Nm dwarf_set_reloc_application
+.Nd set a library-wide relocation flag
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_set_reloc_application
+.Fa "int apply"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_set_reloc_application
+allows applications to specify how relocation information is to be
+handled by the DWARF(3) library.
+.Pp
+If the argument
+.Ar apply
+holds a non-zero value, the library will process all the relevant
+.Dq ".rel"
+and
+.Dq ".rela"
+relocation sections and will apply the relocation records found to
+their corresponding DWARF sections.
+.Pp
+If the argument
+.Ar apply
+is zero, the library will not attempt to apply any relocations.
+.Pp
+The default behaviour of the library is to process relocation records.
+.Sh NOTES
+Function
+.Fn dwarf_set_reloc_application
+should be called before initialising a dwarf debugging context, i.e,
+it should be called by the application before calling either of the
+functions
+.Xr dwarf_init 3
+or
+.Xr dwarf_elf_init 3 .
+.Sh RETURN VALUES
+Function
+.Fn dwarf_set_reloc_application
+returns the previous value of the library-wide relocation application
+flag.
+.Sh ERRORS
+Function
+.Fn dwarf_set_reloc_application
+does not return an error.
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_init 3 ,
+.Xr dwarf_elf_init 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_seterrarg.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,102 @@
+.\" Copyright (c) 2010 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: dwarf_seterrarg.3 2075 2011-10-27 03:47:28Z jkoshy $
+.\"
+.Dd May 01, 2010
+.Os
+.Dt DWARF_SETERRARG 3
+.Sh NAME
+.Nm dwarf_seterrarg ,
+.Nm dwarf_seterrhand
+.Nd configure error handling
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft Dwarf_Ptr
+.Fn dwarf_seterrarg "Dwarf_Debug dbg" "Dwarf_Ptr arg"
+.Ft Dwarf_Handler
+.Fn dwarf_seterrhand "Dwarf_Debug dbg" "Dwarf_Handler handler"
+.Sh DESCRIPTION
+These functions may be used by applications to configure error handling
+callbacks.
+The error handling scheme used by the library is described in
+.Xr dwarf 3 .
+.Pp
+Function
+.Fn dwarf_seterrarg
+may be used to set the callback argument passed to a configured
+error handler at the time it is invoked.
+Argument
+.Ar arg
+is the callback argument being set.
+Argument
+.Ar dbg
+can be a debug context allocated by a prior call to
+.Xr dwarf_init 3 ,
+or can be NULL to indicate that the library-wide callback argument
+is to be set.
+.Pp
+Function
+.Fn dwarf_seterrhand
+may be used to associate an error handler denoted by argument
+.Ar handler
+with the DWARF debug context descriptor denoted by argument
+.Ar dbg .
+Argument
+.Ar dbg
+should be a debug context allocated by a prior call to
+.Xr dwarf_init 3 ,
+or may be NULL to indicate that the library-wide error handler
+is to be set.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_seterrhand
+returns the previous error handler associated with argument
+.Ar dbg .
+If argument
+.Ar dbg
+is NULL, function
+.Fn dwarf_seterrhand
+returns the previous library-wide error handler.
+.Pp
+Function
+.Fn dwarf_seterrarg
+returns the previous callback argument associated with argument
+.Ar dbg .
+If argument
+.Ar dbg
+is NULL, function
+.Fn dwarf_seterrarg
+returns the previous library-wide callback argument.
+.Pp
+.Sh COMPATIBILITY
+The behavior of these functions when argument
+.Ar dbg
+is NULL is a local extension.
+.Sh ERRORS
+These functions do not set an error code.
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_init 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_seterror.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 2010 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_seterror.c 2075 2011-10-27 03:47:28Z jkoshy $");
+
+#define	_SET_FIELD(R, F, V)					\
+	do {							\
+		(R) = (F);					\
+		(F) = (V);					\
+	} while (0)
+
+#define	SET_FIELD(D, R, F)					\
+	do {							\
+		if (D)						\
+			_SET_FIELD(R, (D)->dbg_##F, F);		\
+		else						\
+			_SET_FIELD(R, _libdwarf.F, F);		\
+	} while (0)
+
+Dwarf_Handler
+dwarf_seterrhand(Dwarf_Debug dbg, Dwarf_Handler errhand)
+{
+	Dwarf_Handler oldhandler;
+
+	SET_FIELD(dbg, oldhandler, errhand);
+
+	return (oldhandler);
+}
+
+Dwarf_Ptr
+dwarf_seterrarg(Dwarf_Debug dbg, Dwarf_Ptr errarg)
+{
+	Dwarf_Ptr oldarg;
+
+	SET_FIELD(dbg, oldarg, errarg);
+
+	return (oldarg);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_srcfiles.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,105 @@
+.\" Copyright (c) 2010 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: dwarf_srcfiles.3 2075 2011-10-27 03:47:28Z jkoshy $
+.\"
+.Dd April 28, 2010
+.Os
+.Dt DWARF_SRCFILES 3
+.Sh NAME
+.Nm dwarf_srcfiles
+.Nd retrieve source file information
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_srcfiles
+.Fa "Dwarf_Die die"
+.Fa "char ***filenames"
+.Fa "Dwarf_Signed *filenamecount"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_srcfiles
+returns the source file names associated with a compilation unit.
+Source file names are returned as an array of NUL-terminated strings.
+.Pp
+Argument
+.Ar die
+should reference a DWARF debugging information entry descriptor with
+source file information, see
+.Xr dwarf 3 .
+Argument
+.Ar filenames
+should point to a location that will hold a pointer to the returned array
+of file names.
+Argument
+.Ar filenamecount
+should point to a location that will hold the number of file names returned.
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Ss Memory Management
+The memory areas used for the file names and for array of pointers
+being returned are managed by the DWARF(3) library.
+The application should not attempt to directly free these memory areas.
+Portable code should indicate that the memory areas are to be freed
+by using
+.Xr dwarf_dealloc 3 .
+.Sh RETURN VALUES
+Function
+.Fn dwarf_srcfiles
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_srcfiles
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar die ,
+.Ar filenames
+or
+.Ar filenamecount
+was NULL.
+.It Bq Er DW_DLE_NO_ENTRY
+The compilation unit referenced by argument
+.Ar die
+does not have associated source file information.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of
+this function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_dealloc 3 ,
+.Xr dwarf_srclines 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_srclines.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,163 @@
+.\" Copyright (c) 2010 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: dwarf_srclines.3 2122 2011-11-09 15:35:14Z jkoshy $
+.\"
+.Dd November 9, 2011
+.Os
+.Dt DWARF_SRCLINES 3
+.Sh NAME
+.Nm dwarf_srclines
+.Nd retrieve line number information for a debugging information entry
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_srclines
+.Fa "Dwarf_Die die"
+.Fa "Dwarf_Line **lines"
+.Fa "Dwarf_Signed *nlines"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_srclines
+returns line number information associated with a compilation unit.
+Line number information is returned as an array of
+.Vt Dwarf_Line
+descriptors.
+.Pp
+Argument
+.Ar die
+should reference a DWARF debugging information entry descriptor
+with line number information, see
+.Xr dwarf 3 .
+Argument
+.Ar lines
+should point to a location that will hold a pointer to the returned array
+of
+.Vt Dwarf_Line
+descriptors.
+Argument
+.Ar nlines
+should point to a location that will hold the number of descriptors
+returned.
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Pp
+The returned
+.Vt Dwarf_Line
+descriptors may be passed to the other line number functions in the
+API set to retrieve specific information about each source line.
+.Ss Memory Management
+The memory area used for the array of
+.Vt Dwarf_Line
+descriptors returned in argument
+.Ar lines
+is owned by the
+.Lb libdwarf .
+The application should not attempt to free this pointer.
+Portable code should instead use
+.Fn dwarf_srclines_dealloc
+to indicate that the memory may be freed.
+.Sh RETURN VALUES
+Function
+.Fn dwarf_srclines
+returns
+.Dv DW_DLV_OK
+when it succeeds.
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_srclines
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+One of the arguments
+.Ar die ,
+.Ar lines
+or
+.Ar nlines
+was NULL.
+.It Bq Er DW_DLE_NO_ENTRY
+The compilation unit referenced by argument
+.Ar die
+does not have associated line number information.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of
+this function.
+.El
+.Sh EXAMPLE
+To obtain an array of
+.Vt Dwarf_Line
+descriptors and to retrieve the source file, line number, and virtual address
+associated with each descriptor:
+.Bd -literal -offset indent
+int n;
+Dwarf_Die die;
+Dwarf_Error de;
+char *filename;
+Dwarf_Line *lines;
+Dwarf_Signed nlines;
+Dwarf_Addr lineaddr;
+Dwarf_Unsigned lineno;
+
+/* variable "die" should reference a DIE for a compilation unit */
+
+if (dwarf_srclines(die, &lines, &nlines, &de) != DW_DLV_OK)
+	errx(EXIT_FAILURE, "dwarf_srclines: %s", dwarf_errmsg(de));
+
+for (n = 0; n < nlines; n++) {
+	/* Retrieve the file name for this descriptor. */
+	if (dwarf_linesrc(lines[n], &filename, &de))
+		errx(EXIT_FAILURE, "dwarf_linesrc: %s",
+		    dwarf_errmsg(de));
+
+	/* Retrieve the line number in the source file. */
+	if (dwarf_lineno(lines[n], &lineno, &de))
+		errx(EXIT_FAILURE, "dwarf_lineno: %s",
+		    dwarf_errmsg(de));
+	/* Retrieve the virtual address for this line. */
+	if (dwarf_lineaddr(lines[n], &lineaddr, &de))
+		errx(EXIT_FAILURE, "dwarf_lineaddr: %s",
+		    dwarf_errmsg(de));
+	}
+.Ed
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_line_srcfileno 3 ,
+.Xr dwarf_lineaddr 3 ,
+.Xr dwarf_linebeginstatement 3 ,
+.Xr dwarf_lineblock 3 ,
+.Xr dwarf_lineendsequence 3 ,
+.Xr dwarf_lineno 3 ,
+.Xr dwarf_lineoff 3 ,
+.Xr dwarf_linesrc 3 ,
+.Xr dwarf_srcfiles 3 ,
+.Xr dwarf_srclines_dealloc 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_start_macro_file.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,106 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_start_macro_file.3 2075 2011-10-27 03:47:28Z jkoshy $
+.\"
+.Dd September 25, 2011
+.Os
+.Dt DWARF_START_MACRO_FILE 3
+.Sh NAME
+.Nm dwarf_start_macro_file
+.Nd mark the start of a source file inclusion
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "int"
+.Fo dwarf_start_macro_file
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_Unsigned lineno"
+.Fa "Dwarf_Unsigned fileindex"
+.Fa "Dwarf_Error *err"
+.Fa
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_start_macro_file
+marks the start of a new source file inclusion.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar lineno
+specifies the line number of the source line where the source
+file inclusion occurs.
+A value of zero is used to indicate the file for the compilation unit
+source itself.
+.Pp
+Argument
+.Ar fileindex
+specifies the index of the source file that is being included.
+Valid source file indices are those returned by
+.Xr dwarf_add_file_decl 3 .
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_start_macro_file
+returns
+.Dv DW_DLV_OK .
+In case of an error, function
+.Fn dwarf_start_macro_file
+returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_start_macro_file
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Ar dbg
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_add_file_decl 3 ,
+.Xr dwarf_def_macro 3 ,
+.Xr dwarf_end_macro_file 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3 ,
+.Xr dwarf_undef_macro 3 ,
+.Xr dwarf_vendor_ext 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_str.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_str.c 3295 2016-01-08 22:08:10Z jkoshy $");
+
+int
+dwarf_get_str(Dwarf_Debug dbg, Dwarf_Off offset, char **string,
+    Dwarf_Signed *ret_strlen, Dwarf_Error *error)
+{
+	Dwarf_Section *ds;
+
+	if (dbg == NULL || string == NULL || ret_strlen == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	ds = _dwarf_find_section(dbg, ".debug_str");
+	if (ds == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	if (offset > ds->ds_size) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLV_ERROR);
+	}
+
+	if (offset == ds->ds_size) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	*string = (char *) ds->ds_data + offset;
+	*ret_strlen = strlen(*string);
+
+	return (DW_DLV_OK);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_tag.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,77 @@
+.\" Copyright (c) 2010 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_tag.3 2075 2011-10-27 03:47:28Z jkoshy $
+.\"
+.Dd April 14, 2010
+.Os
+.Dt DWARF_TAG 3
+.Sh NAME
+.Nm dwarf_tag
+.Nd retrieve the tag associated with a DWARF debugging information entry
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fn dwarf_tag "Dwarf_Die die" "Dwarf_Half *tag" "Dwarf_Error *err"
+.Sh DESCRIPTION
+Function
+.Fn dwarf_tag
+retrieves the tag associated with the debugging information entry
+referenced by argument
+.Ar die ,
+and stores it into the location pointed to by argument
+.Ar tag .
+.Pp
+If argument
+.Ar err
+if non-NULL, it will be used to return an error descriptor in case of
+an error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_tag
+returns
+.Dv DW_DLV_OK .
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_tag
+can fail with the following error:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Va die
+or
+.Va tag
+was NULL.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_die_abbrev_code 3 ,
+.Xr dwarf_diename 3 ,
+.Xr dwarf_dieoffset 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_transform_to_disk_form.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,99 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_transform_to_disk_form.3 2075 2011-10-27 03:47:28Z jkoshy $
+.\"
+.Dd August 25, 2011
+.Os
+.Dt DWARF_TRANSFORM_TO_DISK_FORM 3
+.Sh NAME
+.Nm dwarf_transform_to_disk_form
+.Nd transform DWARF information into byte streams
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft Dwarf_Signed
+.Fo dwarf_transform_to_disk_form
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_transform_to_disk_form
+transforms the DWARF information gathered by the producer into
+byte streams for the application to write out as ELF sections.
+If the flag
+.Dv DW_DLC_SYMBOLIC_RELOCATIONS
+is set on the producer, the function will also generate the associated
+relocation arrays.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case
+of an error.
+.Pp
+After a call to this function, the application can call the function
+.Xr dwarf_get_section_bytes 3
+to retrieve the byte streams for each ELF section.
+If the flag
+.Dv DW_DLC_SYMBOLIC_RELOCATIONS
+was set on the descriptor, the application can also call the function
+.Xr dwarf_get_relocation_info 3
+to retrieve the generated relocation arrays.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_transform_to_disk_form
+returns the total number of ELF sections generated.
+In case of an error, function
+.Fn dwarf_transform_to_disk_form
+returns
+.Dv DW_DLV_NOCOUNT
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_transform_to_disk_form
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Argument
+.Ar dbg
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during execution.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_get_relocation_info 3 ,
+.Xr dwarf_get_section_bytes 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_types.m4	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_types.m4 2697 2012-11-24 17:12:36Z kaiwang27 $");
+
+/* WARNING: GENERATED FROM __file__. */
+
+divert(-1)
+include(SRCDIR`/dwarf_nametbl.m4')
+divert(0)
+MAKE_NAMETBL_API(type,Type,type,typenames)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_undef_macro.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,119 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_undef_macro.3 2122 2011-11-09 15:35:14Z jkoshy $
+.\"
+.Dd November 9, 2011
+.Os
+.Dt DWARF_UNDEF_MACRO 3
+.Sh NAME
+.Nm dwarf_undef_macro
+.Nd record the removal of a macro definition
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "int"
+.Fo dwarf_undef_macro
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_Unsigned lineno"
+.Fa "char *name"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_undef_macro
+records the removal of a macro definition in a DWARF producer
+instance.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar lineno
+specifies the line number of the source line where the macro
+definition was removed.
+A value of zero indicates that the macro definition was removed before
+any source files were read.
+.Pp
+Argument
+.Ar name
+should point to a NUL-terminated string containing the name
+of the macro.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_undef_macro
+returns
+.Dv DW_DLV_OK .
+In case of an error, function
+.Fn dwarf_undef_macro
+returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh EXAMPLE
+To record the fact that the macro named
+.Dv _STDIO_H_
+was removed at line 220 of the current macro file, use:
+.Bd -literal -offset indent
+Dwarf_P_Debug dbg;
+Dwarf_Error de;
+
+/* ... Assume 'dbg' refers to a DWARF producer instance... */
+if (dwarf_undef_macro(dbg, 220, "_STDIO_H_", &de) != DW_DLV_OK)
+	errx(EXIT_FAILURE, "dwarf_def_macro failed: %s",
+	    dwarf_errmsg(-1));
+.Ed
+.Sh ERRORS
+Function
+.Fn dwarf_undef_macro
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Either arguments
+.Ar dbg
+or
+.Ar name
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_def_macro 3 ,
+.Xr dwarf_end_macro_file 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3 ,
+.Xr dwarf_start_macro_file 3 ,
+.Xr dwarf_vendor_ext 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_vars.m4	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_vars.m4 2075 2011-10-27 03:47:28Z jkoshy $");
+
+/* WARNING: GENERATED FROM __file__. */
+
+divert(-1)
+include(SRCDIR`/dwarf_nametbl.m4')
+divert(0)
+MAKE_NAMETBL_API(var,Var,var,static_vars)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_vendor_ext.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,110 @@
+.\" Copyright (c) 2011 Kai Wang
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_vendor_ext.3 2075 2011-10-27 03:47:28Z jkoshy $
+.\"
+.Dd September 25, 2011
+.Os
+.Dt DWARF_VENDOR_EXT 3
+.Sh NAME
+.Nm dwarf_vendor_ext
+.Nd add vendor-specific macro information to a DWARF producer instance
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft "int"
+.Fo dwarf_vendor_ext
+.Fa "Dwarf_P_Debug dbg"
+.Fa "Dwarf_Unsigned constant"
+.Fa "char *string"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_vendor_ext
+adds a vendor-specific macro information entry to a DWARF producer
+instance.
+.Pp
+Argument
+.Ar dbg
+should reference a DWARF producer instance allocated using
+.Xr dwarf_producer_init 3
+or
+.Xr dwarf_producer_init_b 3 .
+.Pp
+Argument
+.Ar constant
+specifies a constant value for the macro information entry.
+.Pp
+Argument
+.Ar string
+point to a NUL-terminated string containing the string value
+for the macro information entry.
+.Pp
+If argument
+.Ar err
+is not NULL, it will be used to store error information in case of an
+error.
+.Pp
+The meaning of the arguments
+.Ar constant
+and
+.Ar string
+are not defined by the DWARF specification, but are instead governed
+by application and vendor conventions.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_vendor_ext
+returns
+.Dv DW_DLV_OK .
+In case of an error, function
+.Fn dwarf_vendor_ext
+returns
+.Dv DW_DLV_ERROR
+and sets the argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_vendor_ext
+can fail with:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Either arguments
+.Ar dbg
+or
+.Ar string
+was NULL.
+.It Bq Er DW_DLE_MEMORY
+An out of memory condition was encountered during the execution of the
+function.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_def_macro 3 ,
+.Xr dwarf_end_macro_file 3 ,
+.Xr dwarf_producer_init 3 ,
+.Xr dwarf_producer_init_b 3 ,
+.Xr dwarf_start_macro_file 3 ,
+.Xr dwarf_undef_macro 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_weaks.m4	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: dwarf_weaks.m4 2075 2011-10-27 03:47:28Z jkoshy $");
+
+/* WARNING: GENERATED FROM __file__. */
+
+divert(-1)
+include(SRCDIR`/dwarf_nametbl.m4')
+divert(0)
+MAKE_NAMETBL_API(weak,Weak,weak,weaknames)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/dwarf_whatattr.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,79 @@
+.\" Copyright (c) 2010 Joseph Koshy
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: dwarf_whatattr.3 3181 2015-04-10 13:22:51Z emaste $
+.\"
+.Dd May 22, 2010
+.Os
+.Dt DWARF_WHATATTR 3
+.Sh NAME
+.Nm dwarf_whatattr
+.Nd retrieve the attribute code for a DWARF attribute
+.Sh LIBRARY
+.Lb libdwarf
+.Sh SYNOPSIS
+.In libdwarf.h
+.Ft int
+.Fo dwarf_whatattr
+.Fa "Dwarf_Attribute attr"
+.Fa "Dwarf_Half *retcode"
+.Fa "Dwarf_Error *err"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn dwarf_whatattr
+retrieves the attribute code for the DWARF attribute referenced
+by argument
+.Ar attr ,
+and writes it to the location pointed to by argument
+.Ar retcode .
+If argument
+.Ar err
+is not NULL, it will be used to return an error descriptor in case
+of an error.
+.Sh RETURN VALUES
+On success, function
+.Fn dwarf_whatattr
+returns
+.Dv DW_DLV_OK .
+In case of an error, it returns
+.Dv DW_DLV_ERROR
+and sets argument
+.Ar err .
+.Sh ERRORS
+Function
+.Fn dwarf_whatattr
+can fail with the following error:
+.Bl -tag -width ".Bq Er DW_DLE_ARGUMENT"
+.It Bq Er DW_DLE_ARGUMENT
+Either of argument
+.Va attr
+or
+.Va retcode
+was NULL.
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr dwarf_attr 3 ,
+.Xr dwarf_hasattr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/libdwarf.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,35 @@
+/*-
+ * Copyright (c) 2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: libdwarf.c 3161 2015-02-15 21:43:36Z emaste $");
+
+struct _libdwarf_globals _libdwarf = {
+	.errhand	= NULL,
+	.errarg		= NULL,
+	.applyreloc	= 1
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/libdwarf.h	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,841 @@
+/*-
+ * Copyright (c) 2007 John Birrell (jb@freebsd.org)
+ * Copyright (c) 2009-2011,2014 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: libdwarf.h 3578 2017-09-14 02:21:28Z emaste $
+ */
+
+#ifndef	_LIBDWARF_H_
+#define	_LIBDWARF_H_
+
+#include <libelf.h>
+
+typedef int		Dwarf_Bool;
+typedef uint64_t	Dwarf_Off;
+typedef uint64_t	Dwarf_Unsigned;
+typedef uint16_t	Dwarf_Half;
+typedef uint8_t		Dwarf_Small;
+typedef int64_t		Dwarf_Signed;
+typedef uint64_t	Dwarf_Addr;
+typedef void		*Dwarf_Ptr;
+
+typedef struct _Dwarf_Abbrev	*Dwarf_Abbrev;
+typedef struct _Dwarf_Arange	*Dwarf_Arange;
+typedef struct _Dwarf_ArangeSet	*Dwarf_ArangeSet;
+typedef struct _Dwarf_Attribute	*Dwarf_Attribute;
+typedef struct _Dwarf_Attribute *Dwarf_P_Attribute;
+typedef struct _Dwarf_AttrDef	*Dwarf_AttrDef;
+typedef struct _Dwarf_Cie	*Dwarf_Cie;
+typedef struct _Dwarf_Cie	*Dwarf_P_Cie;
+typedef struct _Dwarf_Debug	*Dwarf_Debug;
+typedef struct _Dwarf_Debug	*Dwarf_P_Debug;
+typedef struct _Dwarf_Die	*Dwarf_Die;
+typedef struct _Dwarf_Die	*Dwarf_P_Die;
+typedef struct _Dwarf_Fde	*Dwarf_Fde;
+typedef struct _Dwarf_Fde	*Dwarf_P_Fde;
+typedef struct _Dwarf_FrameSec	*Dwarf_FrameSec;
+typedef struct _Dwarf_Line	*Dwarf_Line;
+typedef struct _Dwarf_LineFile	*Dwarf_LineFile;
+typedef struct _Dwarf_LineInfo	*Dwarf_LineInfo;
+typedef struct _Dwarf_MacroSet	*Dwarf_MacroSet;
+typedef struct _Dwarf_NamePair	*Dwarf_NamePair;
+typedef struct _Dwarf_NamePair	*Dwarf_Func;
+typedef struct _Dwarf_NamePair	*Dwarf_Global;
+typedef struct _Dwarf_NamePair	*Dwarf_Type;
+typedef struct _Dwarf_NamePair	*Dwarf_Var;
+typedef struct _Dwarf_NamePair	*Dwarf_Weak;
+typedef struct _Dwarf_NameTbl	*Dwarf_NameTbl;
+typedef struct _Dwarf_NameSec	*Dwarf_NameSec;
+typedef struct _Dwarf_P_Expr	*Dwarf_P_Expr;
+typedef struct _Dwarf_Rangelist	*Dwarf_Rangelist;
+
+typedef enum {
+	DW_OBJECT_MSB,
+	DW_OBJECT_LSB
+} Dwarf_Endianness;
+
+typedef struct {
+	Dwarf_Addr addr;
+	Dwarf_Unsigned size;
+	const char *name;
+} Dwarf_Obj_Access_Section;
+
+typedef struct {
+	int (*get_section_info)(void *_obj, Dwarf_Half _index,
+	    Dwarf_Obj_Access_Section *_ret_section, int *_error);
+	Dwarf_Endianness (*get_byte_order)(void *_obj);
+	Dwarf_Small (*get_length_size)(void *_obj);
+	Dwarf_Small (*get_pointer_size)(void *_obj);
+	Dwarf_Unsigned (*get_section_count)(void *_obj);
+	int (*load_section)(void *_obj, Dwarf_Half _index,
+	    Dwarf_Small **_ret_data, int *_error);
+} Dwarf_Obj_Access_Methods;
+
+typedef struct {
+	void *object;
+	const Dwarf_Obj_Access_Methods *methods;
+} Dwarf_Obj_Access_Interface;
+
+typedef int (*Dwarf_Callback_Func)(char *_name, int _size,
+    Dwarf_Unsigned _type, Dwarf_Unsigned _flags, Dwarf_Unsigned _link,
+    Dwarf_Unsigned _info, int *_index, int *_error);
+
+typedef int (*Dwarf_Callback_Func_b)(char *_name, int _size,
+    Dwarf_Unsigned _type, Dwarf_Unsigned _flags, Dwarf_Unsigned _link,
+    Dwarf_Unsigned _info, Dwarf_Unsigned *_index, int *_error);
+
+typedef Dwarf_Unsigned Dwarf_Tag;
+
+typedef struct {
+        Dwarf_Small	lr_atom;
+        Dwarf_Unsigned	lr_number;
+	Dwarf_Unsigned	lr_number2;
+	Dwarf_Unsigned	lr_offset;
+} Dwarf_Loc;
+
+typedef struct {
+	Dwarf_Addr      ld_lopc;
+	Dwarf_Addr      ld_hipc;
+	Dwarf_Half      ld_cents;
+	Dwarf_Loc	*ld_s;
+} Dwarf_Locdesc;
+
+typedef struct {
+	char signature[8];
+} Dwarf_Sig8;
+
+typedef struct {
+	Dwarf_Unsigned	bl_len;
+	Dwarf_Ptr	bl_data;
+} Dwarf_Block;
+
+enum Dwarf_Ranges_Entry_Type {
+	DW_RANGES_ENTRY,
+	DW_RANGES_ADDRESS_SELECTION,
+	DW_RANGES_END
+};
+
+typedef struct {
+	Dwarf_Unsigned	dwr_addr1;
+	Dwarf_Unsigned	dwr_addr2;
+	enum Dwarf_Ranges_Entry_Type dwr_type;
+} Dwarf_Ranges;
+
+enum Dwarf_Form_Class {
+	DW_FORM_CLASS_UNKNOWN,
+	DW_FORM_CLASS_ADDRESS,
+	DW_FORM_CLASS_BLOCK,
+	DW_FORM_CLASS_CONSTANT,
+	DW_FORM_CLASS_EXPRLOC,
+	DW_FORM_CLASS_FLAG,
+	DW_FORM_CLASS_LINEPTR,
+	DW_FORM_CLASS_LOCLISTPTR,
+	DW_FORM_CLASS_MACPTR,
+	DW_FORM_CLASS_RANGELISTPTR,
+	DW_FORM_CLASS_REFERENCE,
+	DW_FORM_CLASS_STRING
+};
+
+#ifndef	DW_FRAME_HIGHEST_NORMAL_REGISTER
+#define	DW_FRAME_HIGHEST_NORMAL_REGISTER 63
+#endif
+
+#define	DW_FRAME_RA_COL		(DW_FRAME_HIGHEST_NORMAL_REGISTER + 1)
+#define	DW_FRAME_STATIC_LINK	(DW_FRAME_HIGHEST_NORMAL_REGISTER + 2)
+
+#ifndef	DW_FRAME_LAST_REG_NUM
+#define DW_FRAME_LAST_REG_NUM	(DW_FRAME_HIGHEST_NORMAL_REGISTER + 3)
+#endif
+
+#ifndef	DW_FRAME_REG_INITIAL_VALUE
+#define	DW_FRAME_REG_INITIAL_VALUE DW_FRAME_SAME_VAL
+#endif
+
+#define	DW_FRAME_UNDEFINED_VAL		1034
+#define DW_FRAME_SAME_VAL		1035
+#define DW_FRAME_CFA_COL3		1436
+
+#define	DW_EXPR_OFFSET 0
+#define	DW_EXPR_VAL_OFFSET 1
+#define	DW_EXPR_EXPRESSION 2
+#define	DW_EXPR_VAL_EXPRESSION 3
+
+/*
+ * Frame operation only for DWARF 2.
+ */
+
+#define DW_FRAME_CFA_COL 0
+
+typedef struct {
+	Dwarf_Small	fp_base_op;
+	Dwarf_Small	fp_extended_op;
+	Dwarf_Half	fp_register;
+	Dwarf_Signed	fp_offset;
+	Dwarf_Off	fp_instr_offset;
+} Dwarf_Frame_Op;
+
+#ifndef	DW_REG_TABLE_SIZE
+#define	DW_REG_TABLE_SIZE	66
+#endif
+
+typedef struct {
+	struct {
+		Dwarf_Small	dw_offset_relevant;
+		Dwarf_Half	dw_regnum;
+		Dwarf_Addr	dw_offset;
+	} rules[DW_REG_TABLE_SIZE];
+} Dwarf_Regtable;
+
+/*
+ * Frame operation for DWARF 3 and DWARF 2.
+ */
+
+typedef struct {
+	Dwarf_Small	fp_base_op;
+	Dwarf_Small	fp_extended_op;
+	Dwarf_Half	fp_register;
+	Dwarf_Unsigned	fp_offset_or_block_len;
+	Dwarf_Small	*fp_expr_block;
+	Dwarf_Off	fp_instr_offset;
+} Dwarf_Frame_Op3;
+
+typedef struct {
+	Dwarf_Small	dw_offset_relevant;
+	Dwarf_Small	dw_value_type;
+	Dwarf_Half	dw_regnum;
+	Dwarf_Unsigned	dw_offset_or_block_len;
+	Dwarf_Ptr	dw_block_ptr;
+} Dwarf_Regtable_Entry3;
+
+typedef struct {
+	Dwarf_Regtable_Entry3	rt3_cfa_rule;
+	Dwarf_Half		rt3_reg_table_size;
+	Dwarf_Regtable_Entry3	*rt3_rules;
+} Dwarf_Regtable3;
+
+typedef struct {
+	Dwarf_Off	dmd_offset;
+	Dwarf_Small	dmd_type;
+	Dwarf_Signed	dmd_lineno;
+	Dwarf_Signed	dmd_fileindex;
+	char		*dmd_macro;
+} Dwarf_Macro_Details;
+
+/*
+ * Symbols denoting allocation types, for use with dwarf_dealloc(3).
+ */
+
+enum Dwarf_Allocation_Type {
+	DW_DLA_ABBREV,
+	DW_DLA_ADDR,
+	DW_DLA_ARANGE,
+	DW_DLA_ATTR,
+	DW_DLA_BLOCK,
+	DW_DLA_BOUNDS,
+	DW_DLA_CIE,
+	DW_DLA_DEBUG,
+	DW_DLA_DIE,
+	DW_DLA_ELLIST,
+	DW_DLA_ERROR,
+	DW_DLA_FDE,
+	DW_DLA_FRAME_BLOCK,
+	DW_DLA_FRAME_OP,
+	DW_DLA_FUNC,
+	DW_DLA_GLOBAL,
+	DW_DLA_LINE,
+	DW_DLA_LINEBUF,
+	DW_DLA_LIST,
+	DW_DLA_LOC,
+	DW_DLA_LOCDESC,
+	DW_DLA_LOC_BLOCK,
+	DW_DLA_RANGES,
+	DW_DLA_STRING,
+	DW_DLA_SUBSCR,
+	DW_DLA_TYPE,
+	DW_DLA_TYPENAME,
+	DW_DLA_VAR,
+	DW_DLA_WEAK
+};
+
+/*
+ * Relocation Type.
+ */
+enum Dwarf_Rel_Type {
+	dwarf_drt_none = 0,
+	dwarf_drt_data_reloc,
+	dwarf_drt_segment_rel,
+	dwarf_drt_first_of_length_pair,
+	dwarf_drt_second_of_length_pair
+};
+
+/*
+ * Relocation Entry.
+ */
+typedef struct Dwarf_Relocation_Data_s {
+	unsigned char drd_type;
+	unsigned char drd_length;
+	Dwarf_Unsigned drd_offset;
+	Dwarf_Unsigned drd_symbol_index;
+} *Dwarf_Relocation_Data;
+
+#define	DWARF_DRD_BUFFER_VERSION	2
+
+/*
+ * Error numbers which are specific to this implementation.
+ */
+enum {
+	DW_DLE_NONE,			/* No error. */
+	DW_DLE_ERROR,			/* An error! */
+	DW_DLE_ARGUMENT,		/* Invalid argument. */
+	DW_DLE_DEBUG_INFO_NULL,		/* Debug info NULL. */
+	DW_DLE_NO_ENTRY,		/* No entry. */
+	DW_DLE_MEMORY,			/* Insufficient memory. */
+	DW_DLE_ELF,			/* ELF error. */
+	DW_DLE_CU_LENGTH_ERROR,		/* Invalid compilation unit data. */
+	DW_DLE_VERSION_STAMP_ERROR,	/* Invalid version. */
+	DW_DLE_DEBUG_ABBREV_NULL,	/* Abbrev not found. */
+	DW_DLE_DIE_NO_CU_CONTEXT,	/* No current compilation unit. */
+	DW_DLE_LOC_EXPR_BAD,		/* Invalid location expression. */
+	DW_DLE_EXPR_LENGTH_BAD,		/* Invalid DWARF expression. */
+	DW_DLE_DEBUG_LOC_SECTION_SHORT,	/* Loclist section too short. */
+	DW_DLE_ATTR_FORM_BAD,		/* Invalid attribute form. */
+	DW_DLE_DEBUG_LINE_LENGTH_BAD,	/* Line info section too short. */
+	DW_DLE_LINE_FILE_NUM_BAD,	/* Invalid file number. */
+	DW_DLE_DIR_INDEX_BAD,		/* Invalid dir index. */
+	DW_DLE_DEBUG_FRAME_LENGTH_BAD,	/* Frame section too short. */
+	DW_DLE_NO_CIE_FOR_FDE,		/* CIE not found for certain FDE. */
+	DW_DLE_FRAME_AUGMENTATION_UNKNOWN, /* Unknown CIE augmentation. */
+	DW_DLE_FRAME_INSTR_EXEC_ERROR,	/* Frame instruction exec error. */
+	DW_DLE_FRAME_VERSION_BAD,	/* Invalid frame section version. */
+	DW_DLE_FRAME_TABLE_COL_BAD,	/* Invalid table column. */
+	DW_DLE_DF_REG_NUM_TOO_HIGH,	/* Insufficient regtable space. */
+	DW_DLE_PC_NOT_IN_FDE_RANGE,	/* PC requested not in the FDE range. */
+	DW_DLE_ARANGE_OFFSET_BAD,	/* Invalid arange offset. */
+	DW_DLE_DEBUG_MACRO_INCONSISTENT,/* Invalid macinfo data. */
+	DW_DLE_ELF_SECT_ERR,		/* Application callback failed. */
+	DW_DLE_NUM			/* Max error number. */
+};
+
+/*
+ * Mapping of SGI libdwarf error codes for comptibility.
+ */
+#define	DW_DLE_DBG_ALLOC			DW_DLE_MEMORY
+#define	DW_DLE_ALLOC_FAIL			DW_DLE_MEMORY
+#define	DW_DLE_SECT_ALLOC			DW_DLE_MEMORY
+#define	DW_DLE_FILE_ENTRY_ALLOC			DW_DLE_MEMORY
+#define	DW_DLE_LINE_ALLOC			DW_DLE_MEMORY
+#define	DW_DLE_FPGM_ALLOC			DW_DLE_MEMORY
+#define	DW_DLE_INCDIR_ALLOC			DW_DLE_MEMORY
+#define	DW_DLE_STRING_ALLOC			DW_DLE_MEMORY
+#define	DW_DLE_CHUNK_ALLOC			DW_DLE_MEMORY
+#define	DW_DLE_CIE_ALLOC			DW_DLE_MEMORY
+#define	DW_DLE_FDE_ALLOC			DW_DLE_MEMORY
+#define	DW_DLE_CIE_OFFS_ALLOC			DW_DLE_MEMORY
+#define	DW_DLE_DIE_ALLOC			DW_DLE_MEMORY
+#define	DW_DLE_ATTR_ALLOC			DW_DLE_MEMORY
+#define	DW_DLE_ABBREV_ALLOC			DW_DLE_MEMORY
+#define	DW_DLE_ADDR_ALLOC			DW_DLE_MEMORY
+#define	DW_DLE_REL_ALLOC			DW_DLE_MEMORY
+#define	DW_DLE_MACINFO_MALLOC_FAIL		DW_DLE_MEMORY
+#define	DW_DLE_DEBUG_MACRO_MALLOC_SPACE		DW_DLE_MEMORY
+#define	DW_DLE_DF_ALLOC_FAIL			DW_DLE_MEMORY
+#define	DW_DLE_RELOC_SECTION_MALLOC_FAIL	DW_DLE_MEMORY
+#define	DW_DLE_DBG_NULL				DW_DLE_ARGUMENT
+#define	DW_DLE_DIE_NULL				DW_DLE_ARGUMENT
+#define	DW_DLE_FDE_NULL				DW_DLE_ARGUMENT
+#define	DW_DLE_CIE_NULL				DW_DLE_ARGUMENT
+#define	DW_DLE_ATTR_NULL			DW_DLE_ARGUMENT
+#define	DW_DLE_GLOBAL_NULL			DW_DLE_ARGUMENT
+#define	DW_DLE_ARANGES_NULL			DW_DLE_ARGUMENT
+#define	DW_DLE_ARANGE_NULL			DW_DLE_ARGUMENT
+#define	DW_DLE_EXPR_NULL			DW_DLE_ARGUMENT
+#define	DW_DLE_FUNC_NULL			DW_DLE_ARGUMENT
+#define	DW_DLE_TYPE_NULL			DW_DLE_ARGUMENT
+#define	DW_DLE_VAR_NULL				DW_DLE_ARGUMENT
+#define	DW_DLE_WEAK_NULL			DW_DLE_ARGUMENT
+#define	DW_DLE_ELF_BEGIN_ERROR			DW_DLE_ELF
+#define	DW_DLE_ELF_GETEHDR_ERROR		DW_DLE_ELF
+#define	DW_DLE_ELF_GETSHDR_ERROR		DW_DLE_ELF
+#define	DW_DLE_ELF_STRPTR_ERROR			DW_DLE_ELF
+#define	DW_DLE_ELF_SECT_ERROR			DW_DLE_ELF
+#define	DW_DLE_ELF_GETIDENT_ERROR		DW_DLE_ELF
+
+typedef struct _Dwarf_Error {
+	int		err_error;	/* DWARF error. */
+	int		err_elferror;	/* ELF error. */
+	const char	*err_func;	/* Function name where error occurred. */
+	int		err_line;	/* Line number where error occurred. */
+	char		err_msg[1024];	/* Formatted error message. */
+} Dwarf_Error;
+
+/*
+ * Dwarf error handler.
+ */
+typedef void (*Dwarf_Handler)(Dwarf_Error, Dwarf_Ptr);
+
+#define	dwarf_errno(error)	error.err_error
+#define	dwarf_errmsg(error)	dwarf_errmsg_(&error)
+
+/*
+ * Return values which have to be compatible with other
+ * implementations of libdwarf.
+ */
+#define DW_DLV_NO_ENTRY		-1
+#define DW_DLV_OK		0
+#define	DW_DLV_ERROR		1
+#define DW_DLV_BADADDR		NULL
+#define DW_DLV_NOCOUNT		((Dwarf_Signed) -1)
+
+/*
+ * Access modes.
+ */
+#define DW_DLC_READ        	0x0001
+#define DW_DLC_WRITE		0x0002
+#define	DW_DLC_RDWR		0x0004
+
+/*
+ * Flags used by libdwarf producer.
+ */
+#define DW_DLC_SIZE_64			0x40000000
+#define DW_DLC_SIZE_32			0x20000000
+#define DW_DLC_OFFSET_SIZE_64		0x10000000
+#define DW_DLC_ISA_MIPS			0x80000000
+#define DW_DLC_ISA_IA64			0x01000000
+#define DW_DLC_STREAM_RELOCATIONS	0x02000000
+#define DW_DLC_SYMBOLIC_RELOCATIONS	0x04000000
+#define DW_DLC_TARGET_BIGENDIAN		0x08000000
+#define DW_DLC_TARGET_LITTLEENDIAN	0x00100000
+
+/*
+ * Instruction set architectures supported by this implementation.
+ */
+enum Dwarf_ISA {
+	DW_ISA_ARM,
+	DW_ISA_IA64,
+	DW_ISA_MIPS,
+	DW_ISA_PPC,
+	DW_ISA_SPARC,
+	DW_ISA_X86,
+	DW_ISA_X86_64,
+	DW_ISA_AARCH64,
+	DW_ISA_RISCV,
+	DW_ISA_MAX
+};
+
+/* Function prototype definitions. */
+#ifdef __cplusplus
+extern "C" {
+#endif
+Dwarf_P_Attribute dwarf_add_AT_comp_dir(Dwarf_P_Die, char *, Dwarf_Error *);
+Dwarf_P_Attribute dwarf_add_AT_const_value_signedint(Dwarf_P_Die, Dwarf_Signed,
+		    Dwarf_Error *);
+Dwarf_P_Attribute dwarf_add_AT_const_value_string(Dwarf_P_Die, char *,
+		    Dwarf_Error *);
+Dwarf_P_Attribute dwarf_add_AT_const_value_unsignedint(Dwarf_P_Die,
+		    Dwarf_Unsigned, Dwarf_Error *);
+Dwarf_P_Attribute dwarf_add_AT_dataref(Dwarf_P_Debug, Dwarf_P_Die, Dwarf_Half,
+		    Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Error *);
+Dwarf_P_Attribute dwarf_add_AT_flag(Dwarf_P_Debug, Dwarf_P_Die, Dwarf_Half,
+		    Dwarf_Small, Dwarf_Error *);
+Dwarf_P_Attribute dwarf_add_AT_location_expr(Dwarf_P_Debug, Dwarf_P_Die,
+		    Dwarf_Half, Dwarf_P_Expr, Dwarf_Error *);
+Dwarf_P_Attribute dwarf_add_AT_name(Dwarf_P_Die, char *, Dwarf_Error *);
+Dwarf_P_Attribute dwarf_add_AT_producer(Dwarf_P_Die, char *, Dwarf_Error *);
+Dwarf_P_Attribute dwarf_add_AT_ref_address(Dwarf_P_Debug, Dwarf_P_Die,
+		    Dwarf_Half, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Error *);
+Dwarf_P_Attribute dwarf_add_AT_reference(Dwarf_P_Debug, Dwarf_P_Die, Dwarf_Half,
+		    Dwarf_P_Die, Dwarf_Error *);
+Dwarf_P_Attribute dwarf_add_AT_signed_const(Dwarf_P_Debug, Dwarf_P_Die,
+		    Dwarf_Half, Dwarf_Signed, Dwarf_Error *);
+Dwarf_P_Attribute dwarf_add_AT_string(Dwarf_P_Debug, Dwarf_P_Die, Dwarf_Half,
+		    char *, Dwarf_Error *);
+Dwarf_P_Attribute dwarf_add_AT_targ_address(Dwarf_P_Debug, Dwarf_P_Die,
+		    Dwarf_Half, Dwarf_Unsigned, Dwarf_Signed, Dwarf_Error *);
+Dwarf_P_Attribute dwarf_add_AT_targ_address_b(Dwarf_P_Debug, Dwarf_P_Die,
+		    Dwarf_Half, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Error *);
+Dwarf_P_Attribute dwarf_add_AT_unsigned_const(Dwarf_P_Debug, Dwarf_P_Die,
+		    Dwarf_Half, Dwarf_Unsigned, Dwarf_Error *);
+Dwarf_Unsigned	dwarf_add_arange(Dwarf_P_Debug, Dwarf_Addr, Dwarf_Unsigned,
+		    Dwarf_Signed, Dwarf_Error *);
+Dwarf_Unsigned	dwarf_add_arange_b(Dwarf_P_Debug, Dwarf_Addr, Dwarf_Unsigned,
+		    Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Addr, Dwarf_Error *);
+Dwarf_Unsigned	dwarf_add_die_to_debug(Dwarf_P_Debug, Dwarf_P_Die,
+		    Dwarf_Error *);
+Dwarf_Unsigned	dwarf_add_directory_decl(Dwarf_P_Debug, char *, Dwarf_Error *);
+Dwarf_Unsigned	dwarf_add_expr_addr(Dwarf_P_Expr, Dwarf_Unsigned,
+		    Dwarf_Signed, Dwarf_Error *);
+Dwarf_Unsigned	dwarf_add_expr_addr_b(Dwarf_P_Expr, Dwarf_Unsigned,
+		    Dwarf_Unsigned, Dwarf_Error *);
+Dwarf_Unsigned	dwarf_add_expr_gen(Dwarf_P_Expr, Dwarf_Small, Dwarf_Unsigned,
+		    Dwarf_Unsigned, Dwarf_Error *);
+Dwarf_P_Fde	dwarf_add_fde_inst(Dwarf_P_Fde, Dwarf_Small, Dwarf_Unsigned,
+		    Dwarf_Unsigned, Dwarf_Error *);
+Dwarf_Unsigned	dwarf_add_file_decl(Dwarf_P_Debug, char *, Dwarf_Unsigned,
+		    Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Error *);
+Dwarf_Unsigned	dwarf_add_frame_cie(Dwarf_P_Debug, char *, Dwarf_Small,
+		    Dwarf_Small, Dwarf_Small, Dwarf_Ptr, Dwarf_Unsigned,
+		    Dwarf_Error *);
+Dwarf_Unsigned	dwarf_add_frame_fde(Dwarf_P_Debug, Dwarf_P_Fde, Dwarf_P_Die,
+		    Dwarf_Unsigned, Dwarf_Addr, Dwarf_Unsigned, Dwarf_Unsigned,
+		    Dwarf_Error *);
+Dwarf_Unsigned	dwarf_add_frame_fde_b(Dwarf_P_Debug, Dwarf_P_Fde, Dwarf_P_Die,
+		    Dwarf_Unsigned, Dwarf_Addr, Dwarf_Unsigned, Dwarf_Unsigned,
+		    Dwarf_Unsigned, Dwarf_Addr, Dwarf_Error *);
+Dwarf_Unsigned	dwarf_add_funcname(Dwarf_P_Debug, Dwarf_P_Die, char *,
+		    Dwarf_Error *);
+Dwarf_Unsigned	dwarf_add_line_entry(Dwarf_P_Debug, Dwarf_Unsigned,
+		    Dwarf_Addr, Dwarf_Unsigned, Dwarf_Signed, Dwarf_Bool,
+		    Dwarf_Bool, Dwarf_Error *);
+Dwarf_Unsigned	dwarf_add_pubname(Dwarf_P_Debug, Dwarf_P_Die, char *,
+		    Dwarf_Error *);
+Dwarf_Unsigned	dwarf_add_typename(Dwarf_P_Debug, Dwarf_P_Die, char *,
+		    Dwarf_Error *);
+Dwarf_Unsigned	dwarf_add_varname(Dwarf_P_Debug, Dwarf_P_Die, char *,
+		    Dwarf_Error *);
+Dwarf_Unsigned	dwarf_add_weakname(Dwarf_P_Debug, Dwarf_P_Die, char *,
+		    Dwarf_Error *);
+int		dwarf_arrayorder(Dwarf_Die, Dwarf_Unsigned *, Dwarf_Error *);
+int		dwarf_attr(Dwarf_Die, Dwarf_Half, Dwarf_Attribute *,
+		    Dwarf_Error *);
+int		dwarf_attrlist(Dwarf_Die, Dwarf_Attribute **,
+		    Dwarf_Signed *, Dwarf_Error *);
+int		dwarf_attroffset(Dwarf_Attribute, Dwarf_Off *, Dwarf_Error *);
+int		dwarf_attrval_flag(Dwarf_Die, Dwarf_Half, Dwarf_Bool *,
+		    Dwarf_Error *);
+int		dwarf_attrval_signed(Dwarf_Die, Dwarf_Half, Dwarf_Signed *,
+		    Dwarf_Error *);
+int		dwarf_attrval_string(Dwarf_Die, Dwarf_Half, const char **,
+		    Dwarf_Error *);
+int		dwarf_attrval_unsigned(Dwarf_Die, Dwarf_Half, Dwarf_Unsigned *,
+		    Dwarf_Error *);
+int		dwarf_bitoffset(Dwarf_Die, Dwarf_Unsigned *, Dwarf_Error *);
+int		dwarf_bitsize(Dwarf_Die, Dwarf_Unsigned *, Dwarf_Error *);
+int		dwarf_bytesize(Dwarf_Die, Dwarf_Unsigned *, Dwarf_Error *);
+int		dwarf_child(Dwarf_Die, Dwarf_Die *, Dwarf_Error *);
+void		dwarf_dealloc(Dwarf_Debug, Dwarf_Ptr, Dwarf_Unsigned);
+int		dwarf_def_macro(Dwarf_P_Debug, Dwarf_Unsigned, char *, char *,
+		    Dwarf_Error *);
+int		dwarf_die_CU_offset(Dwarf_Die, Dwarf_Off *, Dwarf_Error *);
+int		dwarf_die_CU_offset_range(Dwarf_Die, Dwarf_Off *, Dwarf_Off *,
+		    Dwarf_Error *);
+int		dwarf_die_abbrev_code(Dwarf_Die);
+Dwarf_P_Die	dwarf_die_link(Dwarf_P_Die, Dwarf_P_Die, Dwarf_P_Die,
+		    Dwarf_P_Die, Dwarf_P_Die, Dwarf_Error *);
+int		dwarf_diename(Dwarf_Die, char **, Dwarf_Error *);
+int		dwarf_dieoffset(Dwarf_Die, Dwarf_Off *, Dwarf_Error *);
+int		dwarf_elf_init(Elf *, int, Dwarf_Handler, Dwarf_Ptr,
+		    Dwarf_Debug *, Dwarf_Error *);
+int		dwarf_end_macro_file(Dwarf_P_Debug, Dwarf_Error *);
+const char	*dwarf_errmsg_(Dwarf_Error *);
+int		dwarf_expand_frame_instructions(Dwarf_Cie, Dwarf_Ptr,
+		    Dwarf_Unsigned, Dwarf_Frame_Op **, Dwarf_Signed *,
+		    Dwarf_Error *);
+Dwarf_Unsigned	dwarf_expr_current_offset(Dwarf_P_Expr, Dwarf_Error *);
+Dwarf_Addr	dwarf_expr_into_block(Dwarf_P_Expr, Dwarf_Unsigned *,
+		    Dwarf_Error *);
+Dwarf_P_Fde	dwarf_fde_cfa_offset(Dwarf_P_Fde, Dwarf_Unsigned, Dwarf_Signed,
+		    Dwarf_Error *);
+void		dwarf_fde_cie_list_dealloc(Dwarf_Debug, Dwarf_Cie *,
+		    Dwarf_Signed, Dwarf_Fde *, Dwarf_Signed);
+char		*dwarf_find_macro_value_start(char *);
+int		dwarf_finish(Dwarf_Debug, Dwarf_Error *);
+int		dwarf_formaddr(Dwarf_Attribute, Dwarf_Addr *, Dwarf_Error *);
+int		dwarf_formblock(Dwarf_Attribute, Dwarf_Block **, Dwarf_Error *);
+int		dwarf_formexprloc(Dwarf_Attribute, Dwarf_Unsigned *,
+		    Dwarf_Ptr *, Dwarf_Error *);
+int		dwarf_formflag(Dwarf_Attribute, Dwarf_Bool *, Dwarf_Error *);
+int		dwarf_formref(Dwarf_Attribute, Dwarf_Off *, Dwarf_Error *);
+int		dwarf_formsdata(Dwarf_Attribute, Dwarf_Signed *, Dwarf_Error *);
+int		dwarf_formsig8(Dwarf_Attribute, Dwarf_Sig8 *, Dwarf_Error *);
+int		dwarf_formstring(Dwarf_Attribute, char **, Dwarf_Error *);
+int		dwarf_formudata(Dwarf_Attribute, Dwarf_Unsigned *,
+		    Dwarf_Error *);
+int		dwarf_func_cu_offset(Dwarf_Func, Dwarf_Off *, Dwarf_Error *);
+int		dwarf_func_die_offset(Dwarf_Func, Dwarf_Off *,
+		    Dwarf_Error *);
+int		dwarf_func_name_offsets(Dwarf_Func, char **,
+		    Dwarf_Off *, Dwarf_Off *, Dwarf_Error *);
+int		dwarf_funcname(Dwarf_Func, char **, Dwarf_Error *);
+void		dwarf_funcs_dealloc(Dwarf_Debug, Dwarf_Func *, Dwarf_Signed);
+int		dwarf_get_ACCESS_name(unsigned, const char **);
+int		dwarf_get_ATE_name(unsigned, const char **);
+int		dwarf_get_AT_name(unsigned, const char **);
+int		dwarf_get_CC_name(unsigned, const char **);
+int		dwarf_get_CFA_name(unsigned, const char **);
+int		dwarf_get_CHILDREN_name(unsigned, const char **);
+int		dwarf_get_DSC_name(unsigned, const char **);
+int		dwarf_get_DS_name(unsigned, const char **);
+int		dwarf_get_EH_name(unsigned, const char **);
+int		dwarf_get_END_name(unsigned, const char **);
+int		dwarf_get_FORM_name(unsigned, const char **);
+int		dwarf_get_ID_name(unsigned, const char **);
+int		dwarf_get_INL_name(unsigned, const char **);
+int		dwarf_get_LANG_name(unsigned, const char **);
+int		dwarf_get_LNE_name(unsigned, const char **);
+int		dwarf_get_LNS_name(unsigned, const char **);
+int		dwarf_get_MACINFO_name(unsigned, const char **);
+int		dwarf_get_OP_name(unsigned, const char **);
+int		dwarf_get_ORD_name(unsigned, const char **);
+int		dwarf_get_TAG_name(unsigned, const char **);
+int		dwarf_get_VIRTUALITY_name(unsigned, const char **);
+int		dwarf_get_VIS_name(unsigned, const char **);
+int		dwarf_get_abbrev(Dwarf_Debug, Dwarf_Unsigned, Dwarf_Abbrev *,
+		    Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Error *);
+int		dwarf_get_abbrev_children_flag(Dwarf_Abbrev, Dwarf_Signed *,
+		    Dwarf_Error *);
+int		dwarf_get_abbrev_code(Dwarf_Abbrev, Dwarf_Unsigned *,
+		    Dwarf_Error *);
+int		dwarf_get_abbrev_entry(Dwarf_Abbrev, Dwarf_Signed, Dwarf_Half *,
+		    Dwarf_Signed *, Dwarf_Off *, Dwarf_Error *);
+int		dwarf_get_abbrev_tag(Dwarf_Abbrev, Dwarf_Half *, Dwarf_Error *);
+int		dwarf_get_address_size(Dwarf_Debug, Dwarf_Half *,
+		    Dwarf_Error *);
+int		dwarf_get_arange(Dwarf_Arange *, Dwarf_Unsigned, Dwarf_Addr,
+		    Dwarf_Arange *, Dwarf_Error *);
+int		dwarf_get_arange_cu_header_offset(Dwarf_Arange, Dwarf_Off *,
+		    Dwarf_Error *);
+int		dwarf_get_arange_info(Dwarf_Arange, Dwarf_Addr *,
+		    Dwarf_Unsigned *, Dwarf_Off *, Dwarf_Error *);
+int		dwarf_get_aranges(Dwarf_Debug, Dwarf_Arange **, Dwarf_Signed *,
+		    Dwarf_Error *);
+int		dwarf_get_cie_index(Dwarf_Cie, Dwarf_Signed *, Dwarf_Error *);
+int		dwarf_get_cie_info(Dwarf_Cie, Dwarf_Unsigned *, Dwarf_Small *,
+		    char **, Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Half *,
+		    Dwarf_Ptr *, Dwarf_Unsigned *, Dwarf_Error *);
+int		dwarf_get_cie_of_fde(Dwarf_Fde, Dwarf_Cie *, Dwarf_Error *);
+int		dwarf_get_cu_die_offset(Dwarf_Arange, Dwarf_Off *,
+		    Dwarf_Error *);
+int		dwarf_get_cu_die_offset_given_cu_header_offset(Dwarf_Debug,
+		    Dwarf_Off, Dwarf_Off *, Dwarf_Error *);
+int		dwarf_get_cu_die_offset_given_cu_header_offset_b(Dwarf_Debug,
+		    Dwarf_Off, Dwarf_Bool, Dwarf_Off *, Dwarf_Error *);
+Dwarf_Bool	dwarf_get_die_infotypes_flag(Dwarf_Die);
+int		dwarf_get_elf(Dwarf_Debug, Elf **, Dwarf_Error *);
+int		dwarf_get_fde_at_pc(Dwarf_Fde *, Dwarf_Addr, Dwarf_Fde *,
+		    Dwarf_Addr *, Dwarf_Addr *, Dwarf_Error *);
+int		dwarf_get_fde_info_for_all_regs(Dwarf_Fde, Dwarf_Addr,
+		    Dwarf_Regtable *, Dwarf_Addr *, Dwarf_Error *);
+int		dwarf_get_fde_info_for_all_regs3(Dwarf_Fde, Dwarf_Addr,
+		    Dwarf_Regtable3 *, Dwarf_Addr *, Dwarf_Error *);
+int		dwarf_get_fde_info_for_cfa_reg3(Dwarf_Fde, Dwarf_Addr,
+		    Dwarf_Small *, Dwarf_Signed *, Dwarf_Signed *, Dwarf_Signed *,
+		    Dwarf_Ptr *, Dwarf_Addr *, Dwarf_Error *);
+int		dwarf_get_fde_info_for_reg(Dwarf_Fde, Dwarf_Half, Dwarf_Addr,
+		    Dwarf_Signed *, Dwarf_Signed *, Dwarf_Signed *,
+		    Dwarf_Addr *, Dwarf_Error *);
+int		dwarf_get_fde_info_for_reg3(Dwarf_Fde, Dwarf_Half, Dwarf_Addr,
+		    Dwarf_Small *, Dwarf_Signed *, Dwarf_Signed *,
+		    Dwarf_Signed *, Dwarf_Ptr *, Dwarf_Addr *, Dwarf_Error *);
+int		dwarf_get_fde_instr_bytes(Dwarf_Fde, Dwarf_Ptr *,
+		    Dwarf_Unsigned *, Dwarf_Error *);
+int		dwarf_get_fde_list(Dwarf_Debug, Dwarf_Cie **, Dwarf_Signed *,
+		    Dwarf_Fde **, Dwarf_Signed *, Dwarf_Error *);
+int		dwarf_get_fde_list_eh(Dwarf_Debug, Dwarf_Cie **, Dwarf_Signed *,
+		    Dwarf_Fde **, Dwarf_Signed *, Dwarf_Error *);
+int		dwarf_get_fde_n(Dwarf_Fde *, Dwarf_Unsigned, Dwarf_Fde *,
+		    Dwarf_Error *);
+int		dwarf_get_fde_range(Dwarf_Fde, Dwarf_Addr *, Dwarf_Unsigned *,
+		    Dwarf_Ptr *, Dwarf_Unsigned *, Dwarf_Off *, Dwarf_Signed *,
+		    Dwarf_Off *, Dwarf_Error *);
+enum Dwarf_Form_Class dwarf_get_form_class(Dwarf_Half, Dwarf_Half, Dwarf_Half,
+		    Dwarf_Half);
+int		dwarf_get_funcs(Dwarf_Debug, Dwarf_Func **, Dwarf_Signed *,
+		    Dwarf_Error *);
+int		dwarf_get_globals(Dwarf_Debug, Dwarf_Global **, Dwarf_Signed *,
+		    Dwarf_Error *);
+int		dwarf_get_loclist_entry(Dwarf_Debug, Dwarf_Unsigned,
+		    Dwarf_Addr *, Dwarf_Addr *, Dwarf_Ptr *, Dwarf_Unsigned *,
+		    Dwarf_Unsigned *, Dwarf_Error *);
+int		dwarf_get_macro_details(Dwarf_Debug, Dwarf_Off, Dwarf_Unsigned,
+		    Dwarf_Signed *, Dwarf_Macro_Details **, Dwarf_Error *);
+int		dwarf_get_pubtypes(Dwarf_Debug, Dwarf_Type **, Dwarf_Signed *,
+		    Dwarf_Error *);
+int		dwarf_get_ranges(Dwarf_Debug, Dwarf_Off, Dwarf_Ranges **,
+		    Dwarf_Signed *, Dwarf_Unsigned *, Dwarf_Error *);
+int		dwarf_get_ranges_a(Dwarf_Debug, Dwarf_Off, Dwarf_Die,
+		    Dwarf_Ranges **, Dwarf_Signed *, Dwarf_Unsigned *,
+		    Dwarf_Error *);
+int		dwarf_get_relocation_info(Dwarf_P_Debug, Dwarf_Signed *,
+		    Dwarf_Signed *, Dwarf_Unsigned *, Dwarf_Relocation_Data *,
+		    Dwarf_Error *);
+int		dwarf_get_relocation_info_count(Dwarf_P_Debug, Dwarf_Unsigned *,
+		    int *, Dwarf_Error *);
+Dwarf_Ptr	dwarf_get_section_bytes(Dwarf_P_Debug, Dwarf_Signed,
+		    Dwarf_Signed *, Dwarf_Unsigned *, Dwarf_Error *);
+int		dwarf_get_section_max_offsets(Dwarf_Debug, Dwarf_Unsigned *,
+		    Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Unsigned *,
+		    Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Unsigned *,
+		    Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Unsigned *,
+		    Dwarf_Unsigned *);
+int		dwarf_get_section_max_offsets_b(Dwarf_Debug, Dwarf_Unsigned *,
+		    Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Unsigned *,
+		    Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Unsigned *,
+		    Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Unsigned *,
+		    Dwarf_Unsigned *, Dwarf_Unsigned *);
+int		dwarf_get_str(Dwarf_Debug, Dwarf_Off, char **, Dwarf_Signed *,
+		    Dwarf_Error *);
+int		dwarf_get_types(Dwarf_Debug, Dwarf_Type **, Dwarf_Signed *,
+		    Dwarf_Error *);
+int		dwarf_get_vars(Dwarf_Debug, Dwarf_Var **, Dwarf_Signed *,
+		    Dwarf_Error *);
+int		dwarf_get_weaks(Dwarf_Debug, Dwarf_Weak **, Dwarf_Signed *,
+		    Dwarf_Error *);
+int		dwarf_global_cu_offset(Dwarf_Global, Dwarf_Off *, Dwarf_Error *);
+int		dwarf_global_die_offset(Dwarf_Global, Dwarf_Off *,
+		    Dwarf_Error *);
+int		dwarf_global_formref(Dwarf_Attribute, Dwarf_Off *,
+		    Dwarf_Error *);
+int		dwarf_global_name_offsets(Dwarf_Global, char **,
+		    Dwarf_Off *, Dwarf_Off *, Dwarf_Error *);
+void		dwarf_globals_dealloc(Dwarf_Debug, Dwarf_Global *, Dwarf_Signed);
+int		dwarf_globname(Dwarf_Global, char **, Dwarf_Error *);
+int		dwarf_hasattr(Dwarf_Die, Dwarf_Half, Dwarf_Bool *,
+		    Dwarf_Error *);
+int		dwarf_hasform(Dwarf_Attribute, Dwarf_Half, Dwarf_Bool *,
+		    Dwarf_Error *);
+int		dwarf_highpc(Dwarf_Die, Dwarf_Addr *, Dwarf_Error *);
+int		dwarf_highpc_b(Dwarf_Die, Dwarf_Addr *, Dwarf_Half *,
+		    enum Dwarf_Form_Class *, Dwarf_Error *);
+int		dwarf_init(int, int, Dwarf_Handler, Dwarf_Ptr, Dwarf_Debug *,
+		    Dwarf_Error *);
+int		dwarf_line_srcfileno(Dwarf_Line, Dwarf_Unsigned *,
+		    Dwarf_Error *);
+int		dwarf_lineaddr(Dwarf_Line, Dwarf_Addr *, Dwarf_Error *);
+int		dwarf_linebeginstatement(Dwarf_Line, Dwarf_Bool *,
+		    Dwarf_Error *);
+int		dwarf_lineblock(Dwarf_Line, Dwarf_Bool *, Dwarf_Error *);
+int		dwarf_lineendsequence(Dwarf_Line, Dwarf_Bool *, Dwarf_Error *);
+int		dwarf_lineno(Dwarf_Line, Dwarf_Unsigned *, Dwarf_Error *);
+int		dwarf_lineoff(Dwarf_Line, Dwarf_Signed *, Dwarf_Error *);
+int		dwarf_linesrc(Dwarf_Line, char **, Dwarf_Error *);
+Dwarf_Unsigned	dwarf_lne_end_sequence(Dwarf_P_Debug, Dwarf_Addr, Dwarf_Error *);
+Dwarf_Unsigned	dwarf_lne_set_address(Dwarf_P_Debug, Dwarf_Addr, Dwarf_Unsigned,
+		    Dwarf_Error *);
+int		dwarf_loclist(Dwarf_Attribute, Dwarf_Locdesc **, Dwarf_Signed *,
+		    Dwarf_Error *);
+int		dwarf_loclist_from_expr(Dwarf_Debug, Dwarf_Ptr, Dwarf_Unsigned,
+		    Dwarf_Locdesc **, Dwarf_Signed *, Dwarf_Error *);
+int		dwarf_loclist_from_expr_a(Dwarf_Debug, Dwarf_Ptr,
+		    Dwarf_Unsigned, Dwarf_Half, Dwarf_Locdesc **,
+		    Dwarf_Signed *, Dwarf_Error *);
+int		dwarf_loclist_from_expr_b(Dwarf_Debug, Dwarf_Ptr,
+		    Dwarf_Unsigned, Dwarf_Half, Dwarf_Half,
+		    Dwarf_Small, Dwarf_Locdesc **, Dwarf_Signed *,
+		    Dwarf_Error *);
+int		dwarf_loclist_n(Dwarf_Attribute, Dwarf_Locdesc ***,
+		    Dwarf_Signed *, Dwarf_Error *);
+int		dwarf_lowpc(Dwarf_Die, Dwarf_Addr *, Dwarf_Error *);
+Dwarf_P_Die	dwarf_new_die(Dwarf_P_Debug, Dwarf_Tag, Dwarf_P_Die,
+		    Dwarf_P_Die, Dwarf_P_Die, Dwarf_P_Die, Dwarf_Error *);
+Dwarf_P_Expr	dwarf_new_expr(Dwarf_P_Debug, Dwarf_Error *);
+Dwarf_P_Fde	dwarf_new_fde(Dwarf_P_Debug, Dwarf_Error *);
+int		dwarf_next_cu_header(Dwarf_Debug, Dwarf_Unsigned *,
+		    Dwarf_Half *, Dwarf_Off *, Dwarf_Half *,
+		    Dwarf_Unsigned *, Dwarf_Error *);
+int		dwarf_next_cu_header_b(Dwarf_Debug, Dwarf_Unsigned *,
+		    Dwarf_Half *, Dwarf_Off *, Dwarf_Half *, Dwarf_Half *,
+		    Dwarf_Half *, Dwarf_Unsigned *, Dwarf_Error *);
+int		dwarf_next_cu_header_c(Dwarf_Debug, Dwarf_Bool,
+		    Dwarf_Unsigned *, Dwarf_Half *, Dwarf_Off *, Dwarf_Half *,
+		    Dwarf_Half *, Dwarf_Half *, Dwarf_Sig8 *, Dwarf_Unsigned *,
+		    Dwarf_Unsigned *, Dwarf_Error *);
+int		dwarf_next_types_section(Dwarf_Debug, Dwarf_Error *);
+int		dwarf_object_finish(Dwarf_Debug, Dwarf_Error *);
+int		dwarf_object_init(Dwarf_Obj_Access_Interface *, Dwarf_Handler,
+		    Dwarf_Ptr, Dwarf_Debug *, Dwarf_Error *);
+int		dwarf_offdie(Dwarf_Debug, Dwarf_Off, Dwarf_Die *,
+		    Dwarf_Error *);
+int		dwarf_offdie_b(Dwarf_Debug, Dwarf_Off, Dwarf_Bool, Dwarf_Die *,
+		    Dwarf_Error *);
+Dwarf_Unsigned	dwarf_producer_finish(Dwarf_P_Debug, Dwarf_Error *);
+Dwarf_P_Debug	dwarf_producer_init(Dwarf_Unsigned, Dwarf_Callback_Func,
+		    Dwarf_Handler, Dwarf_Ptr, Dwarf_Error *);
+Dwarf_P_Debug	dwarf_producer_init_b(Dwarf_Unsigned, Dwarf_Callback_Func_b,
+		    Dwarf_Handler, Dwarf_Ptr, Dwarf_Error *);
+int		dwarf_producer_set_isa(Dwarf_P_Debug, enum Dwarf_ISA,
+		    Dwarf_Error *);
+int		dwarf_pubtype_cu_offset(Dwarf_Type, Dwarf_Off *, Dwarf_Error *);
+int		dwarf_pubtype_die_offset(Dwarf_Type, Dwarf_Off *,
+		    Dwarf_Error *);
+int		dwarf_pubtype_name_offsets(Dwarf_Type, char **,
+		    Dwarf_Off *, Dwarf_Off *, Dwarf_Error *);
+int		dwarf_pubtypename(Dwarf_Type, char **, Dwarf_Error *);
+void		dwarf_pubtypes_dealloc(Dwarf_Debug, Dwarf_Type *, Dwarf_Signed);
+void		dwarf_ranges_dealloc(Dwarf_Debug, Dwarf_Ranges *, Dwarf_Signed);
+void		dwarf_reset_section_bytes(Dwarf_P_Debug);
+Dwarf_Half	dwarf_set_frame_cfa_value(Dwarf_Debug, Dwarf_Half);
+Dwarf_Half	dwarf_set_frame_rule_initial_value(Dwarf_Debug, Dwarf_Half);
+Dwarf_Half	dwarf_set_frame_rule_table_size(Dwarf_Debug, Dwarf_Half);
+Dwarf_Half	dwarf_set_frame_same_value(Dwarf_Debug, Dwarf_Half);
+Dwarf_Half	dwarf_set_frame_undefined_value(Dwarf_Debug, Dwarf_Half);
+int		dwarf_set_reloc_application(int);
+Dwarf_Ptr	dwarf_seterrarg(Dwarf_Debug, Dwarf_Ptr);
+Dwarf_Handler	dwarf_seterrhand(Dwarf_Debug, Dwarf_Handler);
+int		dwarf_siblingof(Dwarf_Debug, Dwarf_Die, Dwarf_Die *, Dwarf_Error *);
+int		dwarf_siblingof_b(Dwarf_Debug, Dwarf_Die, Dwarf_Die *, Dwarf_Bool,
+		    Dwarf_Error *);
+int		dwarf_srcfiles(Dwarf_Die, char ***, Dwarf_Signed *, Dwarf_Error *);
+int		dwarf_srclang(Dwarf_Die, Dwarf_Unsigned *, Dwarf_Error *);
+int		dwarf_srclines(Dwarf_Die, Dwarf_Line **, Dwarf_Signed *,
+		    Dwarf_Error *);
+void		dwarf_srclines_dealloc(Dwarf_Debug, Dwarf_Line *,
+		    Dwarf_Signed);
+int		dwarf_start_macro_file(Dwarf_P_Debug, Dwarf_Unsigned,
+		    Dwarf_Unsigned, Dwarf_Error *);
+int		dwarf_tag(Dwarf_Die, Dwarf_Half *, Dwarf_Error *);
+Dwarf_Signed	dwarf_transform_to_disk_form(Dwarf_P_Debug, Dwarf_Error *);
+int		dwarf_type_cu_offset(Dwarf_Type, Dwarf_Off *, Dwarf_Error *);
+int		dwarf_type_die_offset(Dwarf_Type, Dwarf_Off *, Dwarf_Error *);
+int		dwarf_type_name_offsets(Dwarf_Type, char **,
+		    Dwarf_Off *, Dwarf_Off *, Dwarf_Error *);
+int		dwarf_typename(Dwarf_Type, char **, Dwarf_Error *);
+void		dwarf_types_dealloc(Dwarf_Debug, Dwarf_Type *, Dwarf_Signed);
+int		dwarf_undef_macro(Dwarf_P_Debug, Dwarf_Unsigned, char *,
+		    Dwarf_Error *);
+int		dwarf_var_cu_offset(Dwarf_Var, Dwarf_Off *, Dwarf_Error *);
+int		dwarf_var_die_offset(Dwarf_Var, Dwarf_Off *,
+		    Dwarf_Error *);
+int		dwarf_var_name_offsets(Dwarf_Var, char **,
+		    Dwarf_Off *, Dwarf_Off *, Dwarf_Error *);
+int		dwarf_varname(Dwarf_Var, char **, Dwarf_Error *);
+void		dwarf_vars_dealloc(Dwarf_Debug, Dwarf_Var *, Dwarf_Signed);
+int		dwarf_vendor_ext(Dwarf_P_Debug, Dwarf_Unsigned, char *,
+		    Dwarf_Error *);
+int		dwarf_weak_cu_offset(Dwarf_Weak, Dwarf_Off *, Dwarf_Error *);
+int		dwarf_weak_die_offset(Dwarf_Weak, Dwarf_Off *,
+		    Dwarf_Error *);
+int		dwarf_weak_name_offsets(Dwarf_Weak, char **,
+		    Dwarf_Off *, Dwarf_Off *, Dwarf_Error *);
+int		dwarf_weakname(Dwarf_Weak, char **, Dwarf_Error *);
+void		dwarf_weaks_dealloc(Dwarf_Debug, Dwarf_Weak *, Dwarf_Signed);
+int		dwarf_whatattr(Dwarf_Attribute, Dwarf_Half *, Dwarf_Error *);
+int		dwarf_whatform(Dwarf_Attribute, Dwarf_Half *, Dwarf_Error *);
+int		dwarf_whatform_direct(Dwarf_Attribute, Dwarf_Half *,
+		    Dwarf_Error *);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_LIBDWARF_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/libdwarf_abbrev.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,266 @@
+/*-
+ * Copyright (c) 2007 John Birrell (jb@freebsd.org)
+ * Copyright (c) 2009-2011 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: libdwarf_abbrev.c 3420 2016-02-27 02:14:05Z emaste $");
+
+int
+_dwarf_abbrev_add(Dwarf_CU cu, uint64_t entry, uint64_t tag, uint8_t children,
+    uint64_t aboff, Dwarf_Abbrev *abp, Dwarf_Error *error)
+{
+	Dwarf_Abbrev ab;
+	Dwarf_Debug dbg;
+
+	dbg = cu != NULL ? cu->cu_dbg : NULL;
+
+	if ((ab = malloc(sizeof(struct _Dwarf_Abbrev))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+
+	/* Initialise the abbrev structure. */
+	ab->ab_entry	= entry;
+	ab->ab_tag	= tag;
+	ab->ab_children	= children;
+	ab->ab_offset	= aboff;
+	ab->ab_length	= 0;	/* fill in later. */
+	ab->ab_atnum	= 0;	/* fill in later. */
+
+	/* Initialise the list of attribute definitions. */
+	STAILQ_INIT(&ab->ab_attrdef);
+
+	/* Add the abbrev to the hash table of the compilation unit. */
+	if (cu != NULL)
+		HASH_ADD(ab_hh, cu->cu_abbrev_hash, ab_entry,
+		    sizeof(ab->ab_entry), ab);
+
+	if (abp != NULL)
+		*abp = ab;
+
+	return (DW_DLE_NONE);
+}
+
+int
+_dwarf_attrdef_add(Dwarf_Debug dbg, Dwarf_Abbrev ab, uint64_t attr,
+    uint64_t form, uint64_t adoff, Dwarf_AttrDef *adp, Dwarf_Error *error)
+{
+	Dwarf_AttrDef ad;
+
+	if (ab == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLE_ARGUMENT);
+	}
+
+	if ((ad = malloc(sizeof(struct _Dwarf_AttrDef))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+
+	/* Initialise the attribute definition structure. */
+	ad->ad_attrib	= attr;
+	ad->ad_form	= form;
+	ad->ad_offset	= adoff;
+
+	/* Add the attribute definition to the list in the abbrev. */
+	STAILQ_INSERT_TAIL(&ab->ab_attrdef, ad, ad_next);
+
+	/* Increase number of attribute counter. */
+	ab->ab_atnum++;
+
+	if (adp != NULL)
+		*adp = ad;
+
+	return (DW_DLE_NONE);
+}
+
+int
+_dwarf_abbrev_parse(Dwarf_Debug dbg, Dwarf_CU cu, Dwarf_Unsigned *offset,
+    Dwarf_Abbrev *abp, Dwarf_Error *error)
+{
+	Dwarf_Section *ds;
+	uint64_t attr;
+	uint64_t entry;
+	uint64_t form;
+	uint64_t aboff;
+	uint64_t adoff;
+	uint64_t tag;
+	uint8_t children;
+	int ret;
+
+	assert(abp != NULL);
+
+	ds = _dwarf_find_section(dbg, ".debug_abbrev");
+	if (ds == NULL || *offset >= ds->ds_size)
+		return (DW_DLE_NO_ENTRY);
+
+	aboff = *offset;
+
+	entry = _dwarf_read_uleb128(ds->ds_data, offset);
+	if (entry == 0) {
+		/* Last entry. */
+		ret = _dwarf_abbrev_add(cu, entry, 0, 0, aboff, abp,
+		    error);
+		if (ret == DW_DLE_NONE) {
+			(*abp)->ab_length = 1;
+			return (ret);
+		} else
+			return (ret);
+	}
+	tag = _dwarf_read_uleb128(ds->ds_data, offset);
+	children = dbg->read(ds->ds_data, offset, 1);
+	if ((ret = _dwarf_abbrev_add(cu, entry, tag, children, aboff,
+	    abp, error)) != DW_DLE_NONE)
+		return (ret);
+
+	/* Parse attribute definitions. */
+	do {
+		adoff = *offset;
+		attr = _dwarf_read_uleb128(ds->ds_data, offset);
+		form = _dwarf_read_uleb128(ds->ds_data, offset);
+		if (attr != 0)
+			if ((ret = _dwarf_attrdef_add(dbg, *abp, attr,
+			    form, adoff, NULL, error)) != DW_DLE_NONE)
+				return (ret);
+	} while (attr != 0);
+
+	(*abp)->ab_length = *offset - aboff;
+
+	return (ret);
+}
+
+int
+_dwarf_abbrev_find(Dwarf_CU cu, uint64_t entry, Dwarf_Abbrev *abp,
+    Dwarf_Error *error)
+{
+	Dwarf_Abbrev ab;
+	Dwarf_Section *ds;
+	Dwarf_Unsigned offset;
+	int ret;
+
+	if (entry == 0)
+		return (DW_DLE_NO_ENTRY);
+
+	/* Check if the desired abbrev entry is already in the hash table. */
+	HASH_FIND(ab_hh, cu->cu_abbrev_hash, &entry, sizeof(entry), ab);
+	if (ab != NULL) {
+		*abp = ab;
+		return (DW_DLE_NONE);
+	}
+
+	if (cu->cu_abbrev_loaded) {
+		return (DW_DLE_NO_ENTRY);
+	}
+
+	/* Load and search the abbrev table. */
+	ds = _dwarf_find_section(cu->cu_dbg, ".debug_abbrev");
+	if (ds == NULL)
+		return (DW_DLE_NO_ENTRY);
+
+	offset = cu->cu_abbrev_offset_cur;
+	while (offset < ds->ds_size) {
+		ret = _dwarf_abbrev_parse(cu->cu_dbg, cu, &offset, &ab, error);
+		if (ret != DW_DLE_NONE)
+			return (ret);
+		if (ab->ab_entry == entry) {
+			cu->cu_abbrev_offset_cur = offset;
+			*abp = ab;
+			return (DW_DLE_NONE);
+		}
+		if (ab->ab_entry == 0) {
+			cu->cu_abbrev_offset_cur = offset;
+			cu->cu_abbrev_loaded = 1;
+			break;
+		}
+	}
+
+	return (DW_DLE_NO_ENTRY);
+}
+
+void
+_dwarf_abbrev_cleanup(Dwarf_CU cu)
+{
+	Dwarf_Abbrev ab, tab;
+	Dwarf_AttrDef ad, tad;
+
+	assert(cu != NULL);
+
+	HASH_ITER(ab_hh, cu->cu_abbrev_hash, ab, tab) {
+		HASH_DELETE(ab_hh, cu->cu_abbrev_hash, ab);
+		STAILQ_FOREACH_SAFE(ad, &ab->ab_attrdef, ad_next, tad) {
+			STAILQ_REMOVE(&ab->ab_attrdef, ad, _Dwarf_AttrDef,
+			    ad_next);
+			free(ad);
+		}
+		free(ab);
+	}
+}
+
+int
+_dwarf_abbrev_gen(Dwarf_P_Debug dbg, Dwarf_Error *error)
+{
+	Dwarf_CU cu;
+	Dwarf_Abbrev ab;
+	Dwarf_AttrDef ad;
+	Dwarf_P_Section ds;
+	int ret;
+
+	cu = STAILQ_FIRST(&dbg->dbg_cu);
+	if (cu == NULL)
+		return (DW_DLE_NONE);
+
+	/* Create .debug_abbrev section. */
+	if ((ret = _dwarf_section_init(dbg, &ds, ".debug_abbrev", 0, error)) !=
+	    DW_DLE_NONE)
+		return (ret);
+
+	for (ab = cu->cu_abbrev_hash; ab != NULL; ab = ab->ab_hh.next) {
+		RCHECK(WRITE_ULEB128(ab->ab_entry));
+		RCHECK(WRITE_ULEB128(ab->ab_tag));
+		RCHECK(WRITE_VALUE(ab->ab_children, 1));
+		STAILQ_FOREACH(ad, &ab->ab_attrdef, ad_next) {
+			RCHECK(WRITE_ULEB128(ad->ad_attrib));
+			RCHECK(WRITE_ULEB128(ad->ad_form));
+		}
+		/* Signal end of attribute spec list. */
+		RCHECK(WRITE_ULEB128(0));
+		RCHECK(WRITE_ULEB128(0));
+	}
+	/* End of abbreviation for this CU. */
+	RCHECK(WRITE_ULEB128(0));
+
+	/* Notify the creation of .debug_abbrev ELF section. */
+	RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error));
+
+	return (DW_DLE_NONE);
+
+gen_fail:
+
+	_dwarf_section_free(dbg, &ds);
+
+	return (ret);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/libdwarf_arange.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,260 @@
+/*-
+ * Copyright (c) 2009-2011 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: libdwarf_arange.c 3029 2014-04-21 23:26:02Z kaiwang27 $");
+
+void
+_dwarf_arange_cleanup(Dwarf_Debug dbg)
+{
+	Dwarf_ArangeSet as, tas;
+	Dwarf_Arange ar, tar;
+
+	STAILQ_FOREACH_SAFE(as, &dbg->dbg_aslist, as_next, tas) {
+		STAILQ_FOREACH_SAFE(ar, &as->as_arlist, ar_next, tar) {
+			STAILQ_REMOVE(&as->as_arlist, ar, _Dwarf_Arange,
+			    ar_next);
+			free(ar);
+		}
+		STAILQ_REMOVE(&dbg->dbg_aslist, as, _Dwarf_ArangeSet, as_next);
+		free(as);
+	}
+
+	if (dbg->dbg_arange_array)
+		free(dbg->dbg_arange_array);
+
+	dbg->dbg_arange_array = NULL;
+	dbg->dbg_arange_cnt = 0;
+}
+
+int
+_dwarf_arange_init(Dwarf_Debug dbg, Dwarf_Error *error)
+{
+	Dwarf_CU cu;
+	Dwarf_ArangeSet as;
+	Dwarf_Arange ar;
+	Dwarf_Section *ds;
+	uint64_t offset, dwarf_size, length, addr, range;
+	int i, ret;
+
+	ret = DW_DLE_NONE;
+
+	if ((ds = _dwarf_find_section(dbg, ".debug_aranges")) == NULL)
+		return (DW_DLE_NONE);
+
+	if (!dbg->dbg_info_loaded) {
+		ret = _dwarf_info_load(dbg, 1, 1, error);
+		if (ret != DW_DLE_NONE)
+			return (ret);
+	}
+
+	offset = 0;
+	while (offset < ds->ds_size) {
+
+		if ((as = malloc(sizeof(struct _Dwarf_ArangeSet))) == NULL) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+			return (DW_DLE_MEMORY);
+		}
+		STAILQ_INIT(&as->as_arlist);
+		STAILQ_INSERT_TAIL(&dbg->dbg_aslist, as, as_next);
+
+		/* Read in the table header. */
+		length = dbg->read(ds->ds_data, &offset, 4);
+		if (length == 0xffffffff) {
+			dwarf_size = 8;
+			length = dbg->read(ds->ds_data, &offset, 8);
+		} else
+			dwarf_size = 4;
+
+		as->as_length = length;
+		as->as_version = dbg->read(ds->ds_data, &offset, 2);
+		if (as->as_version != 2) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
+			ret = DW_DLE_VERSION_STAMP_ERROR;
+			goto fail_cleanup;
+		}
+
+		as->as_cu_offset = dbg->read(ds->ds_data, &offset, dwarf_size);
+		STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {
+			if (cu->cu_offset == as->as_cu_offset)
+				break;
+		}
+		if (cu == NULL) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_ARANGE_OFFSET_BAD);
+			ret = DW_DLE_ARANGE_OFFSET_BAD;
+			goto fail_cleanup;
+		}
+		as->as_cu = cu;
+
+		as->as_addrsz = dbg->read(ds->ds_data, &offset, 1);
+		as->as_segsz = dbg->read(ds->ds_data, &offset, 1);
+
+		/* Skip the padding bytes.  */
+		offset = roundup(offset, 2 * as->as_addrsz);
+
+		/* Read in address range descriptors. */
+		while (offset < ds->ds_size) {
+			addr = dbg->read(ds->ds_data, &offset, as->as_addrsz);
+			range = dbg->read(ds->ds_data, &offset, as->as_addrsz);
+			if (addr == 0 && range == 0)
+				break;
+			if ((ar = calloc(1, sizeof(struct _Dwarf_Arange))) ==
+			    NULL) {
+				DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+				goto fail_cleanup;
+			}
+			ar->ar_as = as;
+			ar->ar_address = addr;
+			ar->ar_range = range;
+			STAILQ_INSERT_TAIL(&as->as_arlist, ar, ar_next);
+			dbg->dbg_arange_cnt++;
+		}
+	}
+
+	/* Build arange array. */
+	if (dbg->dbg_arange_cnt > 0) {
+		if ((dbg->dbg_arange_array = malloc(dbg->dbg_arange_cnt *
+		    sizeof(Dwarf_Arange))) == NULL) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+			ret = DW_DLE_MEMORY;
+			goto fail_cleanup;
+		}
+
+		i = 0;
+		STAILQ_FOREACH(as, &dbg->dbg_aslist, as_next) {
+			STAILQ_FOREACH(ar, &as->as_arlist, ar_next)
+				dbg->dbg_arange_array[i++] = ar;
+		}
+		assert((Dwarf_Unsigned)i == dbg->dbg_arange_cnt);
+	}
+
+	return (DW_DLE_NONE);
+
+fail_cleanup:
+
+	_dwarf_arange_cleanup(dbg);
+
+	return (ret);
+}
+
+int
+_dwarf_arange_gen(Dwarf_P_Debug dbg, Dwarf_Error *error)
+{
+	Dwarf_P_Section ds;
+	Dwarf_Rel_Section drs;
+	Dwarf_ArangeSet as;
+	Dwarf_Arange ar;
+	uint64_t offset;
+	int ret;
+
+	as = dbg->dbgp_as;
+	assert(as != NULL);
+	if (STAILQ_EMPTY(&as->as_arlist))
+		return (DW_DLE_NONE);
+
+	as->as_length = 0;
+	as->as_version = 2;
+	as->as_cu_offset = 0;	/* We have only one CU. */
+	as->as_addrsz = dbg->dbg_pointer_size;
+	as->as_segsz = 0;	/* XXX */
+	
+	/* Create .debug_arange section. */
+	if ((ret = _dwarf_section_init(dbg, &ds, ".debug_aranges", 0, error)) !=
+	    DW_DLE_NONE)
+		goto gen_fail0;
+
+	/* Create relocation section for .debug_aranges */
+	RCHECK(_dwarf_reloc_section_init(dbg, &drs, ds, error));
+
+	/* Write section header. */
+	RCHECK(WRITE_VALUE(as->as_length, 4));
+	RCHECK(WRITE_VALUE(as->as_version, 2));
+	RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc, 4,
+	    ds->ds_size, 0, as->as_cu_offset, ".debug_info", error));
+	RCHECK(WRITE_VALUE(as->as_addrsz, 1));
+	RCHECK(WRITE_VALUE(as->as_segsz, 1));
+
+	/* Pad to (2 * address_size) */
+	offset = roundup(ds->ds_size, 2 * as->as_addrsz);
+	if (offset > ds->ds_size)
+		RCHECK(WRITE_PADDING(0, offset - ds->ds_size));
+
+	/* Write tuples. */
+	STAILQ_FOREACH(ar, &as->as_arlist, ar_next) {
+		RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds,
+		    dwarf_drt_data_reloc, dbg->dbg_pointer_size, ds->ds_size,
+		    ar->ar_symndx, ar->ar_address, NULL, error));
+		if (ar->ar_esymndx > 0)
+			RCHECK(_dwarf_reloc_entry_add_pair(dbg, drs, ds,
+			    dbg->dbg_pointer_size, ds->ds_size, ar->ar_symndx,
+			    ar->ar_esymndx, ar->ar_address, ar->ar_eoff, error));
+		else
+			RCHECK(WRITE_VALUE(ar->ar_range, dbg->dbg_pointer_size));
+	}
+	RCHECK(WRITE_VALUE(0, dbg->dbg_pointer_size));
+	RCHECK(WRITE_VALUE(0, dbg->dbg_pointer_size));
+
+	/* Fill in the length field. */
+	as->as_length = ds->ds_size - 4;
+	offset = 0;
+	dbg->write(ds->ds_data, &offset, as->as_length, 4);
+
+	/* Inform application the creation of .debug_aranges ELF section. */
+	RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error));
+
+	/* Finalize relocation section for .debug_aranges */
+	RCHECK(_dwarf_reloc_section_finalize(dbg, drs, error));
+
+	return (DW_DLE_NONE);
+
+gen_fail:
+	_dwarf_reloc_section_free(dbg, &drs);
+
+gen_fail0:
+	_dwarf_section_free(dbg, &ds);
+
+	return (ret);
+}
+
+void
+_dwarf_arange_pro_cleanup(Dwarf_P_Debug dbg)
+{
+	Dwarf_ArangeSet as;
+	Dwarf_Arange ar, tar;
+
+	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
+	if (dbg->dbgp_as == NULL)
+		return;
+
+	as = dbg->dbgp_as;
+	STAILQ_FOREACH_SAFE(ar, &as->as_arlist, ar_next, tar) {
+		STAILQ_REMOVE(&as->as_arlist, ar, _Dwarf_Arange, ar_next);
+		free(ar);
+	}
+	free(as);
+	dbg->dbgp_as = NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/libdwarf_attr.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,459 @@
+/*-
+ * Copyright (c) 2007 John Birrell (jb@freebsd.org)
+ * Copyright (c) 2009-2011 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: libdwarf_attr.c 3064 2014-06-06 19:35:55Z kaiwang27 $");
+
+int
+_dwarf_attr_alloc(Dwarf_Die die, Dwarf_Attribute *atp, Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+
+	assert(die != NULL);
+	assert(atp != NULL);
+
+	if ((at = calloc(1, sizeof(struct _Dwarf_Attribute))) == NULL) {
+		DWARF_SET_ERROR(die->die_dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+
+	*atp = at;
+
+	return (DW_DLE_NONE);
+}
+
+static int
+_dwarf_attr_add(Dwarf_Die die, Dwarf_Attribute atref, Dwarf_Attribute *atp,
+    Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+	int ret;
+
+	if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
+		return (ret);
+
+	memcpy(at, atref, sizeof(struct _Dwarf_Attribute));
+
+	STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
+
+	/* Save a pointer to the attribute name if this is one. */
+	if (at->at_attrib == DW_AT_name) {
+		switch (at->at_form) {
+		case DW_FORM_strp:
+			die->die_name = at->u[1].s;
+			break;
+		case DW_FORM_string:
+			die->die_name = at->u[0].s;
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (atp != NULL)
+		*atp = at;
+
+	return (DW_DLE_NONE);
+}
+
+Dwarf_Attribute
+_dwarf_attr_find(Dwarf_Die die, Dwarf_Half attr)
+{
+	Dwarf_Attribute at;
+
+	STAILQ_FOREACH(at, &die->die_attr, at_next) {
+		if (at->at_attrib == attr)
+			break;
+	}
+
+	return (at);
+}
+
+int
+_dwarf_attr_init(Dwarf_Debug dbg, Dwarf_Section *ds, uint64_t *offsetp,
+    int dwarf_size, Dwarf_CU cu, Dwarf_Die die, Dwarf_AttrDef ad,
+    uint64_t form, int indirect, Dwarf_Error *error)
+{
+	struct _Dwarf_Attribute atref;
+	Dwarf_Section *str;
+	int ret;
+
+	ret = DW_DLE_NONE;
+	memset(&atref, 0, sizeof(atref));
+	atref.at_die = die;
+	atref.at_offset = *offsetp;
+	atref.at_attrib = ad->ad_attrib;
+	atref.at_form = indirect ? form : ad->ad_form;
+	atref.at_indirect = indirect;
+	atref.at_ld = NULL;
+
+	switch (form) {
+	case DW_FORM_addr:
+		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp,
+		    cu->cu_pointer_size);
+		break;
+	case DW_FORM_block:
+	case DW_FORM_exprloc:
+		atref.u[0].u64 = _dwarf_read_uleb128(ds->ds_data, offsetp);
+		atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
+		    atref.u[0].u64);
+		break;
+	case DW_FORM_block1:
+		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 1);
+		atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
+		    atref.u[0].u64);
+		break;
+	case DW_FORM_block2:
+		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 2);
+		atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
+		    atref.u[0].u64);
+		break;
+	case DW_FORM_block4:
+		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 4);
+		atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
+		    atref.u[0].u64);
+		break;
+	case DW_FORM_data1:
+	case DW_FORM_flag:
+	case DW_FORM_ref1:
+		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 1);
+		break;
+	case DW_FORM_data2:
+	case DW_FORM_ref2:
+		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 2);
+		break;
+	case DW_FORM_data4:
+	case DW_FORM_ref4:
+		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 4);
+		break;
+	case DW_FORM_data8:
+	case DW_FORM_ref8:
+		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 8);
+		break;
+	case DW_FORM_indirect:
+		form = _dwarf_read_uleb128(ds->ds_data, offsetp);
+		return (_dwarf_attr_init(dbg, ds, offsetp, dwarf_size, cu, die,
+		    ad, form, 1, error));
+	case DW_FORM_ref_addr:
+		if (cu->cu_version == 2)
+			atref.u[0].u64 = dbg->read(ds->ds_data, offsetp,
+			    cu->cu_pointer_size);
+		else
+			atref.u[0].u64 = dbg->read(ds->ds_data, offsetp,
+			    dwarf_size);
+		break;
+	case DW_FORM_ref_udata:
+	case DW_FORM_udata:
+		atref.u[0].u64 = _dwarf_read_uleb128(ds->ds_data, offsetp);
+		break;
+	case DW_FORM_sdata:
+		atref.u[0].s64 = _dwarf_read_sleb128(ds->ds_data, offsetp);
+		break;
+	case DW_FORM_sec_offset:
+		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size);
+		break;
+	case DW_FORM_string:
+		atref.u[0].s = _dwarf_read_string(ds->ds_data, ds->ds_size,
+		    offsetp);
+		break;
+	case DW_FORM_strp:
+		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size);
+		str = _dwarf_find_section(dbg, ".debug_str");
+		assert(str != NULL);
+		atref.u[1].s = (char *) str->ds_data + atref.u[0].u64;
+		break;
+	case DW_FORM_ref_sig8:
+		atref.u[0].u64 = 8;
+		atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
+		    atref.u[0].u64);
+		break;
+	case DW_FORM_flag_present:
+		/* This form has no value encoded in the DIE. */
+		atref.u[0].u64 = 1;
+		break;
+	default:
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
+		ret = DW_DLE_ATTR_FORM_BAD;
+		break;
+	}
+
+	if (ret == DW_DLE_NONE) {
+		if (form == DW_FORM_block || form == DW_FORM_block1 ||
+		    form == DW_FORM_block2 || form == DW_FORM_block4) {
+			atref.at_block.bl_len = atref.u[0].u64;
+			atref.at_block.bl_data = atref.u[1].u8p;
+		}
+		ret = _dwarf_attr_add(die, &atref, NULL, error);
+	}
+
+	return (ret);
+}
+
+static int
+_dwarf_attr_write(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_Rel_Section drs,
+    Dwarf_CU cu, Dwarf_Attribute at, int pass2, Dwarf_Error *error)
+{
+	struct _Dwarf_P_Expr_Entry *ee;
+	uint64_t value, offset, bs;
+	int ret;
+
+	assert(dbg != NULL && ds != NULL && cu != NULL && at != NULL);
+
+	/* Fill in reference to other DIE in the second pass. */
+	if (pass2) {
+		if (at->at_form != DW_FORM_ref4 && at->at_form != DW_FORM_ref8)
+			return (DW_DLE_NONE);
+		if (at->at_refdie == NULL || at->at_offset == 0)
+			return (DW_DLE_NONE);
+		offset = at->at_offset;
+		dbg->write(ds->ds_data, &offset, at->at_refdie->die_offset,
+		    at->at_form == DW_FORM_ref4 ? 4 : 8);
+		return (DW_DLE_NONE);
+	}
+
+	switch (at->at_form) {
+	case DW_FORM_addr:
+		if (at->at_relsym)
+			ret = _dwarf_reloc_entry_add(dbg, drs, ds,
+			    dwarf_drt_data_reloc, cu->cu_pointer_size,
+			    ds->ds_size, at->at_relsym, at->u[0].u64, NULL,
+			    error);
+		else
+			ret = WRITE_VALUE(at->u[0].u64, cu->cu_pointer_size);
+		break;
+	case DW_FORM_block:
+	case DW_FORM_block1:
+	case DW_FORM_block2:
+	case DW_FORM_block4:
+		/* Write block size. */
+		if (at->at_form == DW_FORM_block) {
+			ret = _dwarf_write_uleb128_alloc(&ds->ds_data,
+			    &ds->ds_cap, &ds->ds_size, at->u[0].u64, error);
+			if (ret != DW_DLE_NONE)
+				break;
+		} else {
+			if (at->at_form == DW_FORM_block1)
+				bs = 1;
+			else if (at->at_form == DW_FORM_block2)
+				bs = 2;
+			else
+				bs = 4;
+			ret = WRITE_VALUE(at->u[0].u64, bs);
+			if (ret != DW_DLE_NONE)
+				break;
+		}
+
+		/* Keep block data offset for later use. */
+		offset = ds->ds_size;
+
+		/* Write block data. */
+		ret = WRITE_BLOCK(at->u[1].u8p, at->u[0].u64);
+		if (ret != DW_DLE_NONE)
+			break;
+		if (at->at_expr == NULL)
+			break;
+
+		/* Generate relocation entry for DW_OP_addr expressions. */
+		STAILQ_FOREACH(ee, &at->at_expr->pe_eelist, ee_next) {
+			if (ee->ee_loc.lr_atom != DW_OP_addr || ee->ee_sym == 0)
+				continue;
+			ret = _dwarf_reloc_entry_add(dbg, drs, ds,
+			    dwarf_drt_data_reloc, dbg->dbg_pointer_size,
+			    offset + ee->ee_loc.lr_offset + 1, ee->ee_sym,
+			    ee->ee_loc.lr_number, NULL, error);
+			if (ret != DW_DLE_NONE)
+				break;
+		}
+		break;
+	case DW_FORM_data1:
+	case DW_FORM_flag:
+	case DW_FORM_ref1:
+		ret = WRITE_VALUE(at->u[0].u64, 1);
+		break;
+	case DW_FORM_data2:
+	case DW_FORM_ref2:
+		ret = WRITE_VALUE(at->u[0].u64, 2);
+		break;
+	case DW_FORM_data4:
+		if (at->at_relsym || at->at_relsec != NULL)
+			ret = _dwarf_reloc_entry_add(dbg, drs, ds,
+			    dwarf_drt_data_reloc, 4, ds->ds_size, at->at_relsym,
+			    at->u[0].u64, at->at_relsec, error);
+		else
+			ret = WRITE_VALUE(at->u[0].u64, 4);
+		break;
+	case DW_FORM_data8:
+		if (at->at_relsym || at->at_relsec != NULL)
+			ret = _dwarf_reloc_entry_add(dbg, drs, ds,
+			    dwarf_drt_data_reloc, 8, ds->ds_size, at->at_relsym,
+			    at->u[0].u64, at->at_relsec, error);
+		else
+			ret = WRITE_VALUE(at->u[0].u64, 8);
+		break;
+	case DW_FORM_ref4:
+	case DW_FORM_ref8:
+		/*
+		 * The value of ref4 and ref8 could be a reference to another
+		 * DIE within the CU. And if we don't know the ref DIE's
+		 * offset at the moement, then we remember at_offset and fill
+		 * it in the second pass.
+		 */
+		if (at->at_refdie) {
+			value = at->at_refdie->die_offset;
+			if (value == 0) {
+				cu->cu_pass2 = 1;
+				at->at_offset = ds->ds_size;
+			}
+		} else
+			value = at->u[0].u64;
+		ret = WRITE_VALUE(value, at->at_form == DW_FORM_ref4 ? 4 : 8);
+		break;
+	case DW_FORM_indirect:
+		/* TODO. */
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
+		ret = DW_DLE_ATTR_FORM_BAD;
+		break;
+	case DW_FORM_ref_addr:
+		/* DWARF2 format. */
+		if (at->at_relsym)
+			ret = _dwarf_reloc_entry_add(dbg, drs, ds,
+			    dwarf_drt_data_reloc, cu->cu_pointer_size,
+			    ds->ds_size, at->at_relsym, at->u[0].u64, NULL,
+			    error);
+		else
+			ret = WRITE_VALUE(at->u[0].u64, cu->cu_pointer_size);
+		break;
+	case DW_FORM_ref_udata:
+	case DW_FORM_udata:
+		ret = WRITE_ULEB128(at->u[0].u64);
+		break;
+	case DW_FORM_sdata:
+		ret = WRITE_SLEB128(at->u[0].s64);
+		break;
+	case DW_FORM_string:
+		assert(at->u[0].s != NULL);
+		ret = WRITE_STRING(at->u[0].s);
+		break;
+	case DW_FORM_strp:
+		ret = _dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc,
+		    4, ds->ds_size, 0, at->u[0].u64, ".debug_str", error);
+		break;
+	default:
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
+		ret = DW_DLE_ATTR_FORM_BAD;
+		break;
+	}
+
+	return (ret);
+}
+
+int
+_dwarf_add_AT_dataref(Dwarf_P_Debug dbg, Dwarf_P_Die die, Dwarf_Half attr,
+    Dwarf_Unsigned pc_value, Dwarf_Unsigned sym_index, const char *secname,
+    Dwarf_P_Attribute *atp, Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+	int ret;
+
+	assert(dbg != NULL && die != NULL);
+
+	if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
+		return (ret);
+
+	at->at_die = die;
+	at->at_attrib = attr;
+	if (dbg->dbg_pointer_size == 4)
+		at->at_form = DW_FORM_data4;
+	else
+		at->at_form = DW_FORM_data8;
+	at->at_relsym = sym_index;
+	at->at_relsec = secname;
+	at->u[0].u64 = pc_value;
+
+	STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
+
+	if (atp)
+		*atp = at;
+
+	return (DW_DLE_NONE);
+}
+
+int
+_dwarf_add_string_attr(Dwarf_P_Die die, Dwarf_P_Attribute *atp, Dwarf_Half attr,
+    char *string, Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+	Dwarf_Debug dbg;
+	int ret;
+
+	dbg = die != NULL ? die->die_dbg : NULL;
+
+	assert(atp != NULL);
+
+	if (die == NULL || string == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLE_ARGUMENT);
+	}
+
+	if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
+		return (ret);
+
+	at->at_die = die;
+	at->at_attrib = attr;
+	at->at_form = DW_FORM_strp;
+	if ((ret = _dwarf_strtab_add(dbg, string, &at->u[0].u64,
+	    error)) != DW_DLE_NONE) {
+		free(at);
+		return (ret);
+	}
+	at->u[1].s = _dwarf_strtab_get_table(dbg) + at->u[0].u64;
+
+	*atp = at;
+
+	STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
+
+	return (DW_DLE_NONE);
+}
+
+int
+_dwarf_attr_gen(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_Rel_Section drs,
+    Dwarf_CU cu, Dwarf_Die die, int pass2, Dwarf_Error *error)
+{
+	Dwarf_Attribute at;
+	int ret;
+
+	assert(dbg != NULL && ds != NULL && cu != NULL && die != NULL);
+
+	STAILQ_FOREACH(at, &die->die_attr, at_next) {
+		ret = _dwarf_attr_write(dbg, ds, drs, cu, at, pass2, error);
+		if (ret != DW_DLE_NONE)
+			return (ret);
+	}
+
+	return (DW_DLE_NONE);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/libdwarf_die.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,457 @@
+/*-
+ * Copyright (c) 2007 John Birrell (jb@freebsd.org)
+ * Copyright (c) 2009-2011 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: libdwarf_die.c 3039 2014-05-18 15:10:56Z kaiwang27 $");
+
+int
+_dwarf_die_alloc(Dwarf_Debug dbg, Dwarf_Die *ret_die, Dwarf_Error *error)
+{
+	Dwarf_Die die;
+
+	assert(ret_die != NULL);
+
+	if ((die = calloc(1, sizeof(struct _Dwarf_Die))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+
+	STAILQ_INIT(&die->die_attr);
+
+	*ret_die = die;
+
+	return (DW_DLE_NONE);
+}
+
+static int
+_dwarf_die_add(Dwarf_CU cu, uint64_t offset, uint64_t abnum, Dwarf_Abbrev ab,
+    Dwarf_Die *diep, Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+	Dwarf_Die die;
+	int ret;
+
+	assert(cu != NULL);
+	assert(ab != NULL);
+
+	dbg = cu->cu_dbg;
+
+	if ((ret = _dwarf_die_alloc(dbg, &die, error)) != DW_DLE_NONE)
+		return (ret);
+
+	die->die_offset	= offset;
+	die->die_abnum	= abnum;
+	die->die_ab	= ab;
+	die->die_cu	= cu;
+	die->die_dbg	= cu->cu_dbg;
+
+	if (diep != NULL)
+		*diep = die;
+
+	return (DW_DLE_NONE);
+}
+
+/* Find die at offset 'off' within the same CU. */
+Dwarf_Die
+_dwarf_die_find(Dwarf_Die die, Dwarf_Unsigned off)
+{
+	Dwarf_Debug dbg;
+	Dwarf_Section *ds;
+	Dwarf_CU cu;
+	Dwarf_Die die1;
+	Dwarf_Error de;
+	int ret;
+
+	cu = die->die_cu;
+	dbg = die->die_dbg;
+	ds = cu->cu_is_info ? dbg->dbg_info_sec : dbg->dbg_types_sec;
+
+	ret = _dwarf_die_parse(dbg, ds, cu, cu->cu_dwarf_size, off,
+	    cu->cu_next_offset, &die1, 0, &de);
+
+	if (ret == DW_DLE_NONE)
+		return (die1);
+	else
+		return (NULL);
+}
+
+int
+_dwarf_die_parse(Dwarf_Debug dbg, Dwarf_Section *ds, Dwarf_CU cu,
+    int dwarf_size, uint64_t offset, uint64_t next_offset, Dwarf_Die *ret_die,
+    int search_sibling, Dwarf_Error *error)
+{
+	Dwarf_Abbrev ab;
+	Dwarf_AttrDef ad;
+	Dwarf_Die die;
+	uint64_t abnum;
+	uint64_t die_offset;
+	int ret, level;
+
+	assert(cu != NULL);
+
+	level = 1;
+	die = NULL;
+
+	while (offset < next_offset && offset < ds->ds_size) {
+
+		die_offset = offset;
+
+		abnum = _dwarf_read_uleb128(ds->ds_data, &offset);
+
+		if (abnum == 0) {
+			if (level == 0 || !search_sibling)
+				return (DW_DLE_NO_ENTRY);
+
+			/*
+			 * Return to previous DIE level.
+			 */
+			level--;
+			continue;
+		}
+
+		if ((ret = _dwarf_abbrev_find(cu, abnum, &ab, error)) !=
+		    DW_DLE_NONE)
+			return (ret);
+
+		if ((ret = _dwarf_die_add(cu, die_offset, abnum, ab, &die,
+		    error)) != DW_DLE_NONE)
+			return (ret);
+
+		STAILQ_FOREACH(ad, &ab->ab_attrdef, ad_next) {
+			if ((ret = _dwarf_attr_init(dbg, ds, &offset,
+			    dwarf_size, cu, die, ad, ad->ad_form, 0,
+			    error)) != DW_DLE_NONE)
+				return (ret);
+		}
+
+		die->die_next_off = offset;
+		if (search_sibling && level > 0) {
+			dwarf_dealloc(dbg, die, DW_DLA_DIE);
+			if (ab->ab_children == DW_CHILDREN_yes) {
+				/* Advance to next DIE level. */
+				level++;
+			}
+		} else {
+			*ret_die = die;
+			return (DW_DLE_NONE);
+		}
+	}
+
+	return (DW_DLE_NO_ENTRY);
+}
+
+void
+_dwarf_die_link(Dwarf_P_Die die, Dwarf_P_Die parent, Dwarf_P_Die child,
+    Dwarf_P_Die left_sibling, Dwarf_P_Die right_sibling)
+{
+	Dwarf_P_Die last_child;
+
+	assert(die != NULL);
+
+	if (parent) {
+
+		/* Disconnect from old parent. */
+		if (die->die_parent) {
+			if (die->die_parent != parent) {
+				if (die->die_parent->die_child == die)
+					die->die_parent->die_child = NULL;
+				die->die_parent = NULL;
+                     }
+		}
+
+		/* Find the last child of this parent. */
+		last_child = parent->die_child;
+		if (last_child) {
+			while (last_child->die_right != NULL)
+				last_child = last_child->die_right;
+		}
+
+		/* Connect to new parent. */
+		die->die_parent = parent;
+
+		/*
+		 * Attach this DIE to the end of sibling list. If new
+		 * parent doesn't have any child, set this DIE as the
+		 * first child.
+		 */
+		if (last_child) {
+			assert(last_child->die_right == NULL);
+			last_child->die_right = die;
+			die->die_left = last_child;
+		} else
+			parent->die_child = die;
+	}
+
+	if (child) {
+
+		/* Disconnect from old child. */
+		if (die->die_child) {
+			if (die->die_child != child) {
+				die->die_child->die_parent = NULL;
+				die->die_child = NULL;
+			}
+		}
+
+		/* Connect to new child. */
+		die->die_child = child;
+		child->die_parent = die;
+	}
+
+	if (left_sibling) {
+
+		/* Disconnect from old left sibling. */
+		if (die->die_left) {
+			if (die->die_left != left_sibling) {
+				die->die_left->die_right = NULL;
+				die->die_left = NULL;
+			}
+		}
+
+		/* Connect to new right sibling. */
+		die->die_left = left_sibling;
+		left_sibling->die_right = die;
+	}
+
+	if (right_sibling) {
+
+		/* Disconnect from old right sibling. */
+		if (die->die_right) {
+			if (die->die_right != right_sibling) {
+				die->die_right->die_left = NULL;
+				die->die_right = NULL;
+			}
+		}
+
+		/* Connect to new right sibling. */
+		die->die_right = right_sibling;
+		right_sibling->die_left = die;
+	}
+}
+
+int
+_dwarf_die_count_links(Dwarf_P_Die parent, Dwarf_P_Die child,
+    Dwarf_P_Die left_sibling, Dwarf_P_Die right_sibling)
+{
+	int count;
+
+	count = 0;
+
+	if (parent)
+		count++;
+	if (child)
+		count++;
+	if (left_sibling)
+		count++;
+	if (right_sibling)
+		count++;
+
+	return (count);
+}
+
+static int
+_dwarf_die_gen_recursive(Dwarf_P_Debug dbg, Dwarf_CU cu, Dwarf_Rel_Section drs,
+    Dwarf_P_Die die, int pass2, Dwarf_Error *error)
+{
+	Dwarf_P_Section ds;
+	Dwarf_Abbrev ab;
+	Dwarf_Attribute at;
+	Dwarf_AttrDef ad;
+	int match, ret;
+
+	ds = dbg->dbgp_info;
+	assert(ds != NULL);
+
+	if (pass2)
+		goto attr_gen;
+
+	/*
+	 * Add DW_AT_sibling attribute for DIEs with children, so consumers
+	 * can quickly scan chains of siblings, while ignoring the children
+	 * of individual siblings.
+	 */
+	if (die->die_child && die->die_right) {
+		if (_dwarf_attr_find(die, DW_AT_sibling) == NULL)
+			(void) dwarf_add_AT_reference(dbg, die, DW_AT_sibling,
+			    die->die_right, error);
+	}
+
+	/*
+	 * Search abbrev list to find a matching entry.
+	 */
+	die->die_ab = NULL;
+	for (ab = cu->cu_abbrev_hash; ab != NULL; ab = ab->ab_hh.next) {
+		if (die->die_tag != ab->ab_tag)
+			continue;
+		if (ab->ab_children == DW_CHILDREN_no && die->die_child != NULL)
+			continue;
+		if (ab->ab_children == DW_CHILDREN_yes &&
+		    die->die_child == NULL)
+			continue;
+		at = STAILQ_FIRST(&die->die_attr);
+		ad = STAILQ_FIRST(&ab->ab_attrdef);
+		match = 1;
+		while (at != NULL && ad != NULL) {
+			if (at->at_attrib != ad->ad_attrib ||
+			    at->at_form != ad->ad_form) {
+				match = 0;
+				break;
+			}
+			at = STAILQ_NEXT(at, at_next);
+			ad = STAILQ_NEXT(ad, ad_next);
+		}
+		if ((at == NULL && ad != NULL) || (at != NULL && ad == NULL))
+			match = 0;
+		if (match) {
+			die->die_ab = ab;
+			break;
+		}
+	}
+
+	/*
+	 * Create a new abbrev entry if we can not reuse any existing one.
+	 */
+	if (die->die_ab == NULL) {
+		ret = _dwarf_abbrev_add(cu, ++cu->cu_abbrev_cnt, die->die_tag,
+		    die->die_child != NULL ? DW_CHILDREN_yes : DW_CHILDREN_no,
+		    0, &ab, error);
+		if (ret != DW_DLE_NONE)
+			return (ret);
+		STAILQ_FOREACH(at, &die->die_attr, at_next) {
+			ret = _dwarf_attrdef_add(dbg, ab, at->at_attrib,
+			    at->at_form, 0, NULL, error);
+			if (ret != DW_DLE_NONE)
+				return (ret);
+		}
+		die->die_ab = ab;
+	}
+
+	die->die_offset = ds->ds_size;
+
+	/*
+	 * Transform the DIE to bytes stream.
+	 */
+	ret = _dwarf_write_uleb128_alloc(&ds->ds_data, &ds->ds_cap,
+	    &ds->ds_size, die->die_ab->ab_entry, error);
+	if (ret != DW_DLE_NONE)
+		return (ret);
+
+attr_gen:
+
+	/* Transform the attributes of this DIE. */
+	ret = _dwarf_attr_gen(dbg, ds, drs, cu, die, pass2, error);
+	if (ret != DW_DLE_NONE)
+		return (ret);
+
+	/* Proceed to child DIE. */
+	if (die->die_child != NULL) {
+		ret = _dwarf_die_gen_recursive(dbg, cu, drs, die->die_child,
+		    pass2, error);
+		if (ret != DW_DLE_NONE)
+			return (ret);
+	}
+
+	/* Proceed to sibling DIE. */
+	if (die->die_right != NULL) {
+		ret = _dwarf_die_gen_recursive(dbg, cu, drs, die->die_right,
+		    pass2, error);
+		if (ret != DW_DLE_NONE)
+			return (ret);
+	}
+
+	/* Write a null DIE indicating the end of current level. */
+	if (die->die_right == NULL) {
+		ret = _dwarf_write_uleb128_alloc(&ds->ds_data, &ds->ds_cap,
+		    &ds->ds_size, 0, error);
+		if (ret != DW_DLE_NONE)
+			return (ret);
+	}
+
+	return (DW_DLE_NONE);
+}
+
+int
+_dwarf_die_gen(Dwarf_P_Debug dbg, Dwarf_CU cu, Dwarf_Rel_Section drs,
+    Dwarf_Error *error)
+{
+	Dwarf_Abbrev ab, tab;
+	Dwarf_AttrDef ad, tad;
+	Dwarf_Die die;
+	int ret;
+
+	assert(dbg != NULL && cu != NULL);
+	assert(dbg->dbgp_root_die != NULL);
+
+	die = dbg->dbgp_root_die;
+
+	/*
+	 * Insert a DW_AT_stmt_list attribute into root DIE, if there are
+	 * line number information.
+	 */
+	if (!STAILQ_EMPTY(&dbg->dbgp_lineinfo->li_lnlist))
+		RCHECK(_dwarf_add_AT_dataref(dbg, die, DW_AT_stmt_list, 0, 0,
+		    ".debug_line", NULL, error));
+
+	RCHECK(_dwarf_die_gen_recursive(dbg, cu, drs, die, 0, error));
+
+	if (cu->cu_pass2)
+		RCHECK(_dwarf_die_gen_recursive(dbg, cu, drs, die, 1, error));
+
+	return (DW_DLE_NONE);
+
+gen_fail:
+
+	HASH_ITER(ab_hh, cu->cu_abbrev_hash, ab, tab) {
+		HASH_DELETE(ab_hh, cu->cu_abbrev_hash, ab);
+		STAILQ_FOREACH_SAFE(ad, &ab->ab_attrdef, ad_next, tad) {
+			STAILQ_REMOVE(&ab->ab_attrdef, ad, _Dwarf_AttrDef,
+			    ad_next);
+			free(ad);
+		}
+		free(ab);
+	}
+
+	return (ret);
+}
+
+void
+_dwarf_die_pro_cleanup(Dwarf_P_Debug dbg)
+{
+	Dwarf_P_Die die, tdie;
+	Dwarf_P_Attribute at, tat;
+
+	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
+
+	STAILQ_FOREACH_SAFE(die, &dbg->dbgp_dielist, die_pro_next, tdie) {
+		STAILQ_FOREACH_SAFE(at, &die->die_attr, at_next, tat) {
+			STAILQ_REMOVE(&die->die_attr, at, _Dwarf_Attribute,
+			    at_next);
+			free(at);
+		}
+		free(die);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/libdwarf_elf_access.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,164 @@
+/*-
+ * Copyright (c) 2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: libdwarf_elf_access.c 2070 2011-10-27 03:05:32Z jkoshy $");
+
+int
+_dwarf_elf_get_section_info(void *obj, Dwarf_Half ndx,
+    Dwarf_Obj_Access_Section *ret_section, int *error)
+{
+	Dwarf_Elf_Object *e;
+	GElf_Shdr *sh;
+
+	e = obj;
+	assert(e != NULL);
+
+	if (ret_section == NULL) {
+		if (error)
+			*error = DW_DLE_ARGUMENT;
+		return (DW_DLV_ERROR);
+	}
+
+	if (ndx >= e->eo_seccnt) {
+		if (error)
+			*error = DW_DLE_NO_ENTRY;
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	sh = &e->eo_shdr[ndx];
+
+	ret_section->addr = sh->sh_addr;
+	ret_section->size = sh->sh_size;
+
+	ret_section->name = elf_strptr(e->eo_elf, e->eo_strndx, sh->sh_name);
+	if (ret_section->name == NULL) {
+		if (error)
+			*error = DW_DLE_ELF;
+		return (DW_DLV_ERROR);
+	}
+
+	return (DW_DLV_OK);
+}
+
+Dwarf_Endianness
+_dwarf_elf_get_byte_order(void *obj)
+{
+	Dwarf_Elf_Object *e;
+
+	e = obj;
+	assert(e != NULL);
+
+	switch (e->eo_ehdr.e_ident[EI_DATA]) {
+	case ELFDATA2MSB:
+		return (DW_OBJECT_MSB);
+
+	case ELFDATA2LSB:
+	case ELFDATANONE:
+	default:
+		return (DW_OBJECT_LSB);
+	}
+}
+
+Dwarf_Small
+_dwarf_elf_get_length_size(void *obj)
+{
+	Dwarf_Elf_Object *e;
+
+	e = obj;
+	assert(e != NULL);
+
+	if (gelf_getclass(e->eo_elf) == ELFCLASS32)
+		return (4);
+	else if (e->eo_ehdr.e_machine == EM_MIPS)
+		return (8);
+	else
+		return (4);
+}
+
+Dwarf_Small
+_dwarf_elf_get_pointer_size(void *obj)
+{
+	Dwarf_Elf_Object *e;
+
+	e = obj;
+	assert(e != NULL);
+
+	if (gelf_getclass(e->eo_elf) == ELFCLASS32)
+		return (4);
+	else
+		return (8);
+}
+
+Dwarf_Unsigned
+_dwarf_elf_get_section_count(void *obj)
+{
+	Dwarf_Elf_Object *e;
+
+	e = obj;
+	assert(e != NULL);
+
+	return (e->eo_seccnt);
+}
+
+int
+_dwarf_elf_load_section(void *obj, Dwarf_Half ndx, Dwarf_Small** ret_data,
+    int *error)
+{
+	Dwarf_Elf_Object *e;
+	Dwarf_Elf_Data *ed;
+
+	e = obj;
+	assert(e != NULL);
+
+	if (ret_data == NULL) {
+		if (error)
+			*error = DW_DLE_ARGUMENT;
+		return (DW_DLV_ERROR);
+	}
+
+	if (ndx >= e->eo_seccnt) {
+		if (error)
+			*error = DW_DLE_NO_ENTRY;
+		return (DW_DLV_NO_ENTRY);
+	}
+
+	ed = &e->eo_data[ndx];
+
+	if (ed->ed_alloc != NULL)
+		*ret_data = ed->ed_alloc;
+	else {
+		if (ed->ed_data == NULL) {
+			if (error)
+				*error = DW_DLE_NO_ENTRY;
+			return (DW_DLV_NO_ENTRY);
+		}
+		*ret_data = ed->ed_data->d_buf;
+	}
+
+	return (DW_DLV_OK);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/libdwarf_elf_init.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,390 @@
+/*-
+ * Copyright (c) 2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: libdwarf_elf_init.c 3475 2016-05-18 18:11:26Z emaste $");
+
+static const char *debug_name[] = {
+	".debug_abbrev",
+	".debug_aranges",
+	".debug_frame",
+	".debug_info",
+	".debug_types",
+	".debug_line",
+	".debug_pubnames",
+	".eh_frame",
+	".debug_macinfo",
+	".debug_str",
+	".debug_loc",
+	".debug_pubtypes",
+	".debug_ranges",
+	".debug_static_func",
+	".debug_static_vars",
+	".debug_typenames",
+	".debug_weaknames",
+	NULL
+};
+
+static void
+_dwarf_elf_apply_rel_reloc(Dwarf_Debug dbg, void *buf, uint64_t bufsize,
+    Elf_Data *rel_data, Elf_Data *symtab_data, int endian)
+{
+	Dwarf_Unsigned type;
+	GElf_Rel rel;
+	GElf_Sym sym;
+	size_t symndx;
+	uint64_t offset;
+	uint64_t addend;
+	int size, j;
+
+	j = 0;
+	while (gelf_getrel(rel_data, j++, &rel) != NULL) {
+		symndx = GELF_R_SYM(rel.r_info);
+		type = GELF_R_TYPE(rel.r_info);
+
+		if (gelf_getsym(symtab_data, symndx, &sym) == NULL)
+			continue;
+
+		size = _dwarf_get_reloc_size(dbg, type);
+		if (size == 0)
+			continue; /* Unknown or non-absolute relocation. */
+
+		offset = rel.r_offset;
+		if (offset + size >= bufsize)
+			continue;
+
+		if (endian == ELFDATA2MSB)
+			addend = _dwarf_read_msb(buf, &offset, size);
+		else
+			addend = _dwarf_read_lsb(buf, &offset, size);
+
+		offset = rel.r_offset;
+		if (endian == ELFDATA2MSB)
+			_dwarf_write_msb(buf, &offset, sym.st_value + addend,
+			    size);
+		else
+			_dwarf_write_lsb(buf, &offset, sym.st_value + addend,
+			    size);
+	}
+}
+
+static void
+_dwarf_elf_apply_rela_reloc(Dwarf_Debug dbg, void *buf, uint64_t bufsize,
+    Elf_Data *rel_data, Elf_Data *symtab_data, int endian)
+{
+	Dwarf_Unsigned type;
+	GElf_Rela rela;
+	GElf_Sym sym;
+	size_t symndx;
+	uint64_t offset;
+	int size, j;
+
+	j = 0;
+	while (gelf_getrela(rel_data, j++, &rela) != NULL) {
+		symndx = GELF_R_SYM(rela.r_info);
+		type = GELF_R_TYPE(rela.r_info);
+
+		if (gelf_getsym(symtab_data, symndx, &sym) == NULL)
+			continue;
+
+		offset = rela.r_offset;
+		size = _dwarf_get_reloc_size(dbg, type);
+		if (size == 0)
+			continue; /* Unknown or non-absolute relocation. */
+		if (offset + size >= bufsize)
+			continue;
+
+		if (endian == ELFDATA2MSB)
+			_dwarf_write_msb(buf, &offset,
+			    sym.st_value + rela.r_addend, size);
+		else
+			_dwarf_write_lsb(buf, &offset,
+			    sym.st_value + rela.r_addend, size);
+	}
+}
+
+static int
+_dwarf_elf_relocate(Dwarf_Debug dbg, Elf *elf, Dwarf_Elf_Data *ed, size_t shndx,
+    size_t symtab, Elf_Data *symtab_data, Dwarf_Error *error)
+{
+	GElf_Ehdr eh;
+	GElf_Shdr sh;
+	Elf_Scn *scn;
+	Elf_Data *rel;
+	int elferr;
+
+	if (symtab == 0 || symtab_data == NULL)
+		return (DW_DLE_NONE);
+
+	if (gelf_getehdr(elf, &eh) == NULL) {
+		DWARF_SET_ELF_ERROR(dbg, error);
+		return (DW_DLE_ELF);
+	}
+
+	scn = NULL;
+	(void) elf_errno();
+	while ((scn = elf_nextscn(elf, scn)) != NULL) {
+		if (gelf_getshdr(scn, &sh) == NULL) {
+			DWARF_SET_ELF_ERROR(dbg, error);
+			return (DW_DLE_ELF);
+		}
+
+		if ((sh.sh_type != SHT_REL && sh.sh_type != SHT_RELA) ||
+		     sh.sh_size == 0)
+			continue;
+
+		if (sh.sh_info == shndx && sh.sh_link == symtab) {
+			if ((rel = elf_getdata(scn, NULL)) == NULL) {
+				elferr = elf_errno();
+				if (elferr != 0) {
+					_DWARF_SET_ERROR(NULL, error,
+					    DW_DLE_ELF, elferr);
+					return (DW_DLE_ELF);
+				} else
+					return (DW_DLE_NONE);
+			}
+
+			ed->ed_alloc = malloc(ed->ed_data->d_size);
+			if (ed->ed_alloc == NULL) {
+				DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+				return (DW_DLE_MEMORY);
+			}
+			memcpy(ed->ed_alloc, ed->ed_data->d_buf,
+			    ed->ed_data->d_size);
+			if (sh.sh_type == SHT_REL)
+				_dwarf_elf_apply_rel_reloc(dbg,
+				    ed->ed_alloc, ed->ed_data->d_size,
+				    rel, symtab_data, eh.e_ident[EI_DATA]);
+			else
+				_dwarf_elf_apply_rela_reloc(dbg,
+				    ed->ed_alloc, ed->ed_data->d_size,
+				    rel, symtab_data, eh.e_ident[EI_DATA]);
+
+			return (DW_DLE_NONE);
+		}
+	}
+	elferr = elf_errno();
+	if (elferr != 0) {
+		DWARF_SET_ELF_ERROR(dbg, error);
+		return (DW_DLE_ELF);
+	}
+
+	return (DW_DLE_NONE);
+}
+
+int
+_dwarf_elf_init(Dwarf_Debug dbg, Elf *elf, Dwarf_Error *error)
+{
+	Dwarf_Obj_Access_Interface *iface;
+	Dwarf_Elf_Object *e;
+	const char *name;
+	GElf_Shdr sh;
+	Elf_Scn *scn;
+	Elf_Data *symtab_data;
+	size_t symtab_ndx;
+	int elferr, i, j, n, ret;
+
+	ret = DW_DLE_NONE;
+
+	if ((iface = calloc(1, sizeof(*iface))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+
+	if ((e = calloc(1, sizeof(*e))) == NULL) {
+		free(iface);
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+
+	e->eo_elf = elf;
+	e->eo_methods.get_section_info = _dwarf_elf_get_section_info;
+	e->eo_methods.get_byte_order = _dwarf_elf_get_byte_order;
+	e->eo_methods.get_length_size = _dwarf_elf_get_length_size;
+	e->eo_methods.get_pointer_size = _dwarf_elf_get_pointer_size;
+	e->eo_methods.get_section_count = _dwarf_elf_get_section_count;
+	e->eo_methods.load_section = _dwarf_elf_load_section;
+
+	iface->object = e;
+	iface->methods = &e->eo_methods;
+
+	dbg->dbg_iface = iface;
+
+	if (gelf_getehdr(elf, &e->eo_ehdr) == NULL) {
+		DWARF_SET_ELF_ERROR(dbg, error);
+		ret = DW_DLE_ELF;
+		goto fail_cleanup;
+	}
+
+	dbg->dbg_machine = e->eo_ehdr.e_machine;
+
+	if (!elf_getshstrndx(elf, &e->eo_strndx)) {
+		DWARF_SET_ELF_ERROR(dbg, error);
+		ret = DW_DLE_ELF;
+		goto fail_cleanup;
+	}
+
+	n = 0;
+	symtab_ndx = 0;
+	symtab_data = NULL;
+	scn = NULL;
+	(void) elf_errno();
+	while ((scn = elf_nextscn(elf, scn)) != NULL) {
+		if (gelf_getshdr(scn, &sh) == NULL) {
+			DWARF_SET_ELF_ERROR(dbg, error);
+			ret = DW_DLE_ELF;
+			goto fail_cleanup;
+		}
+
+		if ((name = elf_strptr(elf, e->eo_strndx, sh.sh_name)) ==
+		    NULL) {
+			DWARF_SET_ELF_ERROR(dbg, error);
+			ret = DW_DLE_ELF;
+			goto fail_cleanup;
+		}
+
+		if (!strcmp(name, ".symtab")) {
+			symtab_ndx = elf_ndxscn(scn);
+			if ((symtab_data = elf_getdata(scn, NULL)) == NULL) {
+				elferr = elf_errno();
+				if (elferr != 0) {
+					_DWARF_SET_ERROR(NULL, error,
+					    DW_DLE_ELF, elferr);
+					ret = DW_DLE_ELF;
+					goto fail_cleanup;
+				}
+			}
+			continue;
+		}
+
+		for (i = 0; debug_name[i] != NULL; i++) {
+			if (!strcmp(name, debug_name[i]))
+				n++;
+		}
+	}
+	elferr = elf_errno();
+	if (elferr != 0) {
+		DWARF_SET_ELF_ERROR(dbg, error);
+		return (DW_DLE_ELF);
+	}
+
+	e->eo_seccnt = n;
+
+	if (n == 0)
+		return (DW_DLE_NONE);
+
+	if ((e->eo_data = calloc(n, sizeof(Dwarf_Elf_Data))) == NULL ||
+	    (e->eo_shdr = calloc(n, sizeof(GElf_Shdr))) == NULL) {
+		DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
+		ret = DW_DLE_MEMORY;
+		goto fail_cleanup;
+	}
+
+	scn = NULL;
+	j = 0;
+	while ((scn = elf_nextscn(elf, scn)) != NULL && j < n) {
+		if (gelf_getshdr(scn, &sh) == NULL) {
+			DWARF_SET_ELF_ERROR(dbg, error);
+			ret = DW_DLE_ELF;
+			goto fail_cleanup;
+		}
+
+		memcpy(&e->eo_shdr[j], &sh, sizeof(sh));
+
+		if ((name = elf_strptr(elf, e->eo_strndx, sh.sh_name)) ==
+		    NULL) {
+			DWARF_SET_ELF_ERROR(dbg, error);
+			ret = DW_DLE_ELF;
+			goto fail_cleanup;
+		}
+
+		for (i = 0; debug_name[i] != NULL; i++) {
+			if (strcmp(name, debug_name[i]))
+				continue;
+
+			(void) elf_errno();
+			if ((e->eo_data[j].ed_data = elf_getdata(scn, NULL)) ==
+			    NULL) {
+				elferr = elf_errno();
+				if (elferr != 0) {
+					_DWARF_SET_ERROR(dbg, error,
+					    DW_DLE_ELF, elferr);
+					ret = DW_DLE_ELF;
+					goto fail_cleanup;
+				}
+			}
+
+			if (_libdwarf.applyreloc) {
+				if (_dwarf_elf_relocate(dbg, elf,
+				    &e->eo_data[j], elf_ndxscn(scn), symtab_ndx,
+				    symtab_data, error) != DW_DLE_NONE)
+					goto fail_cleanup;
+			}
+
+			j++;
+		}
+	}
+
+	assert(j == n);
+
+	return (DW_DLE_NONE);
+
+fail_cleanup:
+
+	_dwarf_elf_deinit(dbg);
+
+	return (ret);
+}
+
+void
+_dwarf_elf_deinit(Dwarf_Debug dbg)
+{
+	Dwarf_Obj_Access_Interface *iface;
+	Dwarf_Elf_Object *e;
+	int i;
+
+	iface = dbg->dbg_iface;
+	assert(iface != NULL);
+
+	e = iface->object;
+	assert(e != NULL);
+
+	if (e->eo_data) {
+		for (i = 0; (Dwarf_Unsigned) i < e->eo_seccnt; i++) {
+			if (e->eo_data[i].ed_alloc)
+				free(e->eo_data[i].ed_alloc);
+		}
+		free(e->eo_data);
+	}
+	if (e->eo_shdr)
+		free(e->eo_shdr);
+
+	free(e);
+	free(iface);
+
+	dbg->dbg_iface = NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/libdwarf_error.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c) 2010 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: libdwarf_error.c 2070 2011-10-27 03:05:32Z jkoshy $");
+
+void
+_dwarf_set_error(Dwarf_Debug dbg, Dwarf_Error *error, int errorcode,
+    int elferrorcode, const char *functionname, int linenumber)
+{
+	Dwarf_Error de;
+
+	de.err_error = errorcode;
+	de.err_elferror = elferrorcode;
+	de.err_func  = functionname;
+	de.err_line  = linenumber;
+	de.err_msg[0] = '\0';
+	
+	/*
+	 * If the user supplied a destination for the error, copy the
+	 * error descriptor over and return.  Otherwise, if the debug
+	 * context is known and has an error handler, invoke that.
+	 * Otherwise, if a 'default' error handler was registered,
+	 * invoke it.
+	 */
+	if (error)
+		*error = de;
+	else if (dbg && dbg->dbg_errhand)
+		dbg->dbg_errhand(de, dbg->dbg_errarg);
+	else if (_libdwarf.errhand)
+		_libdwarf.errhand(de, _libdwarf.errarg);
+
+	/* No handler found, do nothing. */
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/libdwarf_frame.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,1608 @@
+/*-
+ * Copyright (c) 2009-2011,2014 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: libdwarf_frame.c 3589 2018-03-13 20:34:33Z kaiwang27 $");
+
+static int
+_dwarf_frame_find_cie(Dwarf_FrameSec fs, Dwarf_Unsigned offset,
+    Dwarf_Cie *ret_cie)
+{
+	Dwarf_Cie cie;
+
+	STAILQ_FOREACH(cie, &fs->fs_cielist, cie_next) {
+		if (cie->cie_offset == offset)
+			break;
+	}
+
+	if (cie == NULL)
+		return (DW_DLE_NO_ENTRY);
+
+	if (ret_cie != NULL)
+		*ret_cie = cie;
+
+	return (DW_DLE_NONE);
+}
+
+static int
+_dwarf_frame_read_lsb_encoded(Dwarf_Debug dbg, Dwarf_Cie cie, uint64_t *val,
+    uint8_t *data, uint64_t *offsetp, uint8_t encode, Dwarf_Addr pc,
+    Dwarf_Error *error)
+{
+	uint8_t application;
+
+	if (encode == DW_EH_PE_omit)
+		return (DW_DLE_NONE);
+
+	application = encode & 0xf0;
+	encode &= 0x0f;
+
+	switch (encode) {
+	case DW_EH_PE_absptr:
+		*val = dbg->read(data, offsetp, cie->cie_addrsize);
+		break;
+	case DW_EH_PE_uleb128:
+		*val = _dwarf_read_uleb128(data, offsetp);
+		break;
+	case DW_EH_PE_udata2:
+		*val = dbg->read(data, offsetp, 2);
+		break;
+	case DW_EH_PE_udata4:
+		*val = dbg->read(data, offsetp, 4);
+		break;
+	case DW_EH_PE_udata8:
+		*val = dbg->read(data, offsetp, 8);
+		break;
+	case DW_EH_PE_sleb128:
+		*val = _dwarf_read_sleb128(data, offsetp);
+		break;
+	case DW_EH_PE_sdata2:
+		*val = (int16_t) dbg->read(data, offsetp, 2);
+		break;
+	case DW_EH_PE_sdata4:
+		*val = (int32_t) dbg->read(data, offsetp, 4);
+		break;
+	case DW_EH_PE_sdata8:
+		*val = dbg->read(data, offsetp, 8);
+		break;
+	default:
+		DWARF_SET_ERROR(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
+		return (DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
+	}
+
+	if (application == DW_EH_PE_pcrel) {
+		/*
+		 * Value is relative to .eh_frame section virtual addr.
+		 */
+		switch (encode) {
+		case DW_EH_PE_uleb128:
+		case DW_EH_PE_udata2:
+		case DW_EH_PE_udata4:
+		case DW_EH_PE_udata8:
+			*val += pc;
+			break;
+		case DW_EH_PE_sleb128:
+		case DW_EH_PE_sdata2:
+		case DW_EH_PE_sdata4:
+		case DW_EH_PE_sdata8:
+			*val = pc + (int64_t) *val;
+			break;
+		default:
+			/* DW_EH_PE_absptr is absolute value. */
+			break;
+		}
+	}
+
+	/* XXX Applications other than DW_EH_PE_pcrel are not handled. */
+
+	return (DW_DLE_NONE);
+}
+
+static int
+_dwarf_frame_parse_lsb_cie_augment(Dwarf_Debug dbg, Dwarf_Cie cie,
+    Dwarf_Error *error)
+{
+	uint8_t *aug_p, *augdata_p;
+	uint64_t val, offset;
+	uint8_t encode;
+	int ret;
+
+	assert(cie->cie_augment != NULL && *cie->cie_augment == 'z');
+
+	/*
+	 * Here we're only interested in the presence of augment 'R'
+	 * and associated CIE augment data, which describes the
+	 * encoding scheme of FDE PC begin and range.
+	 */
+	aug_p = &cie->cie_augment[1];
+	augdata_p = cie->cie_augdata;
+	while (*aug_p != '\0') {
+		switch (*aug_p) {
+		case 'S':
+			break;
+		case 'L':
+			/* Skip one augment in augment data. */
+			augdata_p++;
+			break;
+		case 'P':
+			/* Skip two augments in augment data. */
+			encode = *augdata_p++;
+			offset = 0;
+			ret = _dwarf_frame_read_lsb_encoded(dbg, cie, &val,
+			    augdata_p, &offset, encode, 0, error);
+			if (ret != DW_DLE_NONE)
+				return (ret);
+			augdata_p += offset;
+			break;
+		case 'R':
+			cie->cie_fde_encode = *augdata_p++;
+			break;
+		default:
+			DWARF_SET_ERROR(dbg, error,
+			    DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
+			return (DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
+		}
+		aug_p++;
+	}
+
+	return (DW_DLE_NONE);
+}
+
+static int
+_dwarf_frame_add_cie(Dwarf_Debug dbg, Dwarf_FrameSec fs, Dwarf_Section *ds,
+    Dwarf_Unsigned *off, Dwarf_Cie *ret_cie, Dwarf_Error *error)
+{
+	Dwarf_Cie cie;
+	uint64_t length;
+	int dwarf_size, ret;
+	char *p;
+
+	/* Check if we already added this CIE. */
+	if (_dwarf_frame_find_cie(fs, *off, &cie) != DW_DLE_NO_ENTRY) {
+		*off += cie->cie_length + 4;
+		return (DW_DLE_NONE);
+	}
+
+	if ((cie = calloc(1, sizeof(struct _Dwarf_Cie))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+	STAILQ_INSERT_TAIL(&fs->fs_cielist, cie, cie_next);
+
+	cie->cie_dbg = dbg;
+	cie->cie_index = fs->fs_cielen;
+	cie->cie_offset = *off;
+
+	length = dbg->read(ds->ds_data, off, 4);
+	if (length == 0xffffffff) {
+		dwarf_size = 8;
+		length = dbg->read(ds->ds_data, off, 8);
+	} else
+		dwarf_size = 4;
+
+	if (length > ds->ds_size - *off) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
+		return (DW_DLE_DEBUG_FRAME_LENGTH_BAD);
+	}
+
+	(void) dbg->read(ds->ds_data, off, dwarf_size); /* Skip CIE id. */
+	cie->cie_length = length;
+
+	cie->cie_version = dbg->read(ds->ds_data, off, 1);
+	if (cie->cie_version != 1 && cie->cie_version != 3 &&
+	    cie->cie_version != 4) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_FRAME_VERSION_BAD);
+		return (DW_DLE_FRAME_VERSION_BAD);
+	}
+
+	cie->cie_augment = ds->ds_data + *off;
+	p = (char *) ds->ds_data;
+	while (p[(*off)++] != '\0')
+		;
+
+	/* We only recognize normal .dwarf_frame and GNU .eh_frame sections. */
+	if (*cie->cie_augment != 0 && *cie->cie_augment != 'z') {
+		*off = cie->cie_offset + ((dwarf_size == 4) ? 4 : 12) +
+		    cie->cie_length;
+		return (DW_DLE_NONE);
+	}
+
+	/* Optional EH Data field for .eh_frame section. */
+	if (strstr((char *)cie->cie_augment, "eh") != NULL)
+		cie->cie_ehdata = dbg->read(ds->ds_data, off,
+		    dbg->dbg_pointer_size);
+
+	/* DWARF4 added "address_size" and "segment_size". */
+	if (cie->cie_version == 4) {
+		cie->cie_addrsize = dbg->read(ds->ds_data, off, 1);
+		cie->cie_segmentsize = dbg->read(ds->ds_data, off, 1);
+	} else {
+		/*
+		 * Otherwise (DWARF[23]) we just set CIE addrsize to the
+		 * debug context pointer size.
+		 */
+		cie->cie_addrsize = dbg->dbg_pointer_size;
+	}
+
+	cie->cie_caf = _dwarf_read_uleb128(ds->ds_data, off);
+	cie->cie_daf = _dwarf_read_sleb128(ds->ds_data, off);
+
+	/* Return address register. */
+	if (cie->cie_version == 1)
+		cie->cie_ra = dbg->read(ds->ds_data, off, 1);
+	else
+		cie->cie_ra = _dwarf_read_uleb128(ds->ds_data, off);
+
+	/* Optional CIE augmentation data for .eh_frame section. */
+	if (*cie->cie_augment == 'z') {
+		cie->cie_auglen = _dwarf_read_uleb128(ds->ds_data, off);
+		cie->cie_augdata = ds->ds_data + *off;
+		*off += cie->cie_auglen;
+		/*
+		 * XXX Use DW_EH_PE_absptr for default FDE PC start/range,
+		 * in case _dwarf_frame_parse_lsb_cie_augment fails to
+		 * find out the real encode.
+		 */
+		cie->cie_fde_encode = DW_EH_PE_absptr;
+		ret = _dwarf_frame_parse_lsb_cie_augment(dbg, cie, error);
+		if (ret != DW_DLE_NONE)
+			return (ret);
+	}
+
+	/* CIE Initial instructions. */
+	cie->cie_initinst = ds->ds_data + *off;
+	if (dwarf_size == 4)
+		cie->cie_instlen = cie->cie_offset + 4 + length - *off;
+	else
+		cie->cie_instlen = cie->cie_offset + 12 + length - *off;
+
+	*off += cie->cie_instlen;
+
+#ifdef FRAME_DEBUG
+	printf("cie:\n");
+	printf("\tcie_version=%u cie_offset=%ju cie_length=%ju cie_augment=%s"
+	    " cie_instlen=%ju cie->cie_caf=%ju cie->cie_daf=%jd off=%ju\n",
+	    cie->cie_version, cie->cie_offset, cie->cie_length,
+	    (char *)cie->cie_augment, cie->cie_instlen, cie->cie_caf,
+	    cie->cie_daf, *off);
+#endif
+
+	if (ret_cie != NULL)
+		*ret_cie = cie;
+
+	fs->fs_cielen++;
+
+	return (DW_DLE_NONE);
+}
+
+static int
+_dwarf_frame_add_fde(Dwarf_Debug dbg, Dwarf_FrameSec fs, Dwarf_Section *ds,
+    Dwarf_Unsigned *off, int eh_frame, Dwarf_Error *error)
+{
+	Dwarf_Cie cie;
+	Dwarf_Fde fde;
+	Dwarf_Unsigned cieoff;
+	uint64_t length, val;
+	int dwarf_size, ret;
+
+	if ((fde = calloc(1, sizeof(struct _Dwarf_Fde))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+	STAILQ_INSERT_TAIL(&fs->fs_fdelist, fde, fde_next);
+
+	fde->fde_dbg = dbg;
+	fde->fde_fs = fs;
+	fde->fde_addr = ds->ds_data + *off;
+	fde->fde_offset = *off;
+
+	length = dbg->read(ds->ds_data, off, 4);
+	if (length == 0xffffffff) {
+		dwarf_size = 8;
+		length = dbg->read(ds->ds_data, off, 8);
+	} else
+		dwarf_size = 4;
+
+	if (length > ds->ds_size - *off) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
+		return (DW_DLE_DEBUG_FRAME_LENGTH_BAD);
+	}
+
+	fde->fde_length = length;
+
+	if (eh_frame) {
+		fde->fde_cieoff = dbg->read(ds->ds_data, off, 4);
+		cieoff = *off - (4 + fde->fde_cieoff);
+		/* This delta should never be 0. */
+		if (cieoff == fde->fde_offset) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_NO_CIE_FOR_FDE);
+			return (DW_DLE_NO_CIE_FOR_FDE);
+		}
+	} else {
+		fde->fde_cieoff = dbg->read(ds->ds_data, off, dwarf_size);
+		cieoff = fde->fde_cieoff;
+	}
+
+	if (_dwarf_frame_find_cie(fs, cieoff, &cie) ==
+	    DW_DLE_NO_ENTRY) {
+		ret = _dwarf_frame_add_cie(dbg, fs, ds, &cieoff, &cie,
+		    error);
+		if (ret != DW_DLE_NONE)
+			return (ret);
+	}
+	fde->fde_cie = cie;
+	if (eh_frame) {
+		/*
+		 * The FDE PC start/range for .eh_frame is encoded according
+		 * to the LSB spec's extension to DWARF2.
+		 */
+		ret = _dwarf_frame_read_lsb_encoded(dbg, cie, &val,
+		    ds->ds_data, off, cie->cie_fde_encode, ds->ds_addr + *off,
+		    error);
+		if (ret != DW_DLE_NONE)
+			return (ret);
+		fde->fde_initloc = val;
+		/*
+		 * FDE PC range should not be relative value to anything.
+		 * So pass 0 for pc value.
+		 */
+		ret = _dwarf_frame_read_lsb_encoded(dbg, cie, &val,
+		    ds->ds_data, off, cie->cie_fde_encode, 0, error);
+		if (ret != DW_DLE_NONE)
+			return (ret);
+		fde->fde_adrange = val;
+	} else {
+		fde->fde_initloc = dbg->read(ds->ds_data, off,
+		    cie->cie_addrsize);
+		fde->fde_adrange = dbg->read(ds->ds_data, off,
+		    cie->cie_addrsize);
+	}
+
+	/* Optional FDE augmentation data for .eh_frame section. (ignored) */
+	if (eh_frame && *cie->cie_augment == 'z') {
+		fde->fde_auglen = _dwarf_read_uleb128(ds->ds_data, off);
+		fde->fde_augdata = ds->ds_data + *off;
+		*off += fde->fde_auglen;
+	}
+
+	fde->fde_inst = ds->ds_data + *off;
+	if (dwarf_size == 4)
+		fde->fde_instlen = fde->fde_offset + 4 + length - *off;
+	else
+		fde->fde_instlen = fde->fde_offset + 12 + length - *off;
+
+	*off += fde->fde_instlen;
+
+#ifdef FRAME_DEBUG
+	printf("fde:");
+	if (eh_frame)
+		printf("(eh_frame)");
+	putchar('\n');
+	printf("\tfde_offset=%ju fde_length=%ju fde_cieoff=%ju"
+	    " fde_instlen=%ju off=%ju\n", fde->fde_offset, fde->fde_length,
+	    fde->fde_cieoff, fde->fde_instlen, *off);
+#endif
+
+	fs->fs_fdelen++;
+
+	return (DW_DLE_NONE);
+}
+
+static void
+_dwarf_frame_section_cleanup(Dwarf_FrameSec fs)
+{
+	Dwarf_Cie cie, tcie;
+	Dwarf_Fde fde, tfde;
+
+	STAILQ_FOREACH_SAFE(cie, &fs->fs_cielist, cie_next, tcie) {
+		STAILQ_REMOVE(&fs->fs_cielist, cie, _Dwarf_Cie, cie_next);
+		free(cie);
+	}
+
+	STAILQ_FOREACH_SAFE(fde, &fs->fs_fdelist, fde_next, tfde) {
+		STAILQ_REMOVE(&fs->fs_fdelist, fde, _Dwarf_Fde, fde_next);
+		free(fde);
+	}
+
+	if (fs->fs_ciearray != NULL)
+		free(fs->fs_ciearray);
+	if (fs->fs_fdearray != NULL)
+		free(fs->fs_fdearray);
+
+	free(fs);
+}
+
+static int
+_dwarf_frame_section_init(Dwarf_Debug dbg, Dwarf_FrameSec *frame_sec,
+    Dwarf_Section *ds, int eh_frame, Dwarf_Error *error)
+{
+	Dwarf_FrameSec fs;
+	Dwarf_Cie cie;
+	Dwarf_Fde fde;
+	uint64_t length, offset, cie_id, entry_off;
+	int dwarf_size, i, ret;
+
+	assert(frame_sec != NULL);
+	assert(*frame_sec == NULL);
+
+	if ((fs = calloc(1, sizeof(struct _Dwarf_FrameSec))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+	STAILQ_INIT(&fs->fs_cielist);
+	STAILQ_INIT(&fs->fs_fdelist);
+
+	offset = 0;
+	while (offset < ds->ds_size) {
+		entry_off = offset;
+		length = dbg->read(ds->ds_data, &offset, 4);
+		if (length == 0xffffffff) {
+			dwarf_size = 8;
+			length = dbg->read(ds->ds_data, &offset, 8);
+		} else
+			dwarf_size = 4;
+
+		if (length > ds->ds_size - offset ||
+		    (length == 0 && !eh_frame)) {
+			DWARF_SET_ERROR(dbg, error,
+			    DW_DLE_DEBUG_FRAME_LENGTH_BAD);
+			return (DW_DLE_DEBUG_FRAME_LENGTH_BAD);
+		}
+
+		/* Check terminator for .eh_frame */
+		if (eh_frame && length == 0)
+			break;
+
+		cie_id = dbg->read(ds->ds_data, &offset, dwarf_size);
+
+		if (eh_frame) {
+			/* GNU .eh_frame use CIE id 0. */
+			if (cie_id == 0)
+				ret = _dwarf_frame_add_cie(dbg, fs, ds,
+				    &entry_off, NULL, error);
+			else
+				ret = _dwarf_frame_add_fde(dbg, fs, ds,
+				    &entry_off, 1, error);
+		} else {
+			/* .dwarf_frame use CIE id ~0 */
+			if ((dwarf_size == 4 && cie_id == ~0U) ||
+			    (dwarf_size == 8 && cie_id == ~0ULL))
+				ret = _dwarf_frame_add_cie(dbg, fs, ds,
+				    &entry_off, NULL, error);
+			else
+				ret = _dwarf_frame_add_fde(dbg, fs, ds,
+				    &entry_off, 0, error);
+		}
+
+		if (ret != DW_DLE_NONE)
+			goto fail_cleanup;
+
+		offset = entry_off;
+	}
+
+	/* Create CIE array. */
+	if (fs->fs_cielen > 0) {
+		if ((fs->fs_ciearray = malloc(sizeof(Dwarf_Cie) *
+		    fs->fs_cielen)) == NULL) {
+			ret = DW_DLE_MEMORY;
+			DWARF_SET_ERROR(dbg, error, ret);
+			goto fail_cleanup;
+		}
+		i = 0;
+		STAILQ_FOREACH(cie, &fs->fs_cielist, cie_next) {
+			fs->fs_ciearray[i++] = cie;
+		}
+		assert((Dwarf_Unsigned)i == fs->fs_cielen);
+	}
+
+	/* Create FDE array. */
+	if (fs->fs_fdelen > 0) {
+		if ((fs->fs_fdearray = malloc(sizeof(Dwarf_Fde) *
+		    fs->fs_fdelen)) == NULL) {
+			ret = DW_DLE_MEMORY;
+			DWARF_SET_ERROR(dbg, error, ret);
+			goto fail_cleanup;
+		}
+		i = 0;
+		STAILQ_FOREACH(fde, &fs->fs_fdelist, fde_next) {
+			fs->fs_fdearray[i++] = fde;
+		}
+		assert((Dwarf_Unsigned)i == fs->fs_fdelen);
+	}
+
+	*frame_sec = fs;
+
+	return (DW_DLE_NONE);
+
+fail_cleanup:
+
+	_dwarf_frame_section_cleanup(fs);
+
+	return (ret);
+}
+
+static int
+_dwarf_frame_run_inst(Dwarf_Debug dbg, Dwarf_Regtable3 *rt, uint8_t addr_size,
+    uint8_t *insts, Dwarf_Unsigned len, Dwarf_Unsigned caf, Dwarf_Signed daf,
+    Dwarf_Addr pc, Dwarf_Addr pc_req, Dwarf_Addr *row_pc, Dwarf_Error *error)
+{
+	Dwarf_Regtable3 *init_rt, *saved_rt;
+	uint8_t *p, *pe;
+	uint8_t high2, low6;
+	uint64_t reg, reg2, uoff, soff;
+	int ret;
+
+#define	CFA	rt->rt3_cfa_rule
+#define	INITCFA	init_rt->rt3_cfa_rule
+#define	RL	rt->rt3_rules
+#define	INITRL	init_rt->rt3_rules
+
+#define CHECK_TABLE_SIZE(x)						\
+	do {								\
+		if ((x) >= rt->rt3_reg_table_size) {			\
+			DWARF_SET_ERROR(dbg, error,			\
+			    DW_DLE_DF_REG_NUM_TOO_HIGH);		\
+			ret = DW_DLE_DF_REG_NUM_TOO_HIGH;		\
+			goto program_done;				\
+		}							\
+	} while(0)
+
+#ifdef FRAME_DEBUG
+	printf("frame_run_inst: (caf=%ju, daf=%jd)\n", caf, daf);
+#endif
+
+	ret = DW_DLE_NONE;
+	init_rt = saved_rt = NULL;
+	*row_pc = pc;
+
+	/* Save a copy of the table as initial state. */
+	_dwarf_frame_regtable_copy(dbg, &init_rt, rt, error);
+
+	p = insts;
+	pe = p + len;
+
+	while (p < pe) {
+
+#ifdef FRAME_DEBUG
+		printf("p=%p pe=%p pc=%#jx pc_req=%#jx\n", p, pe, pc, pc_req);
+#endif
+
+		if (*p == DW_CFA_nop) {
+#ifdef FRAME_DEBUG
+			printf("DW_CFA_nop\n");
+#endif
+			p++;
+			continue;
+		}
+
+		high2 = *p & 0xc0;
+		low6 = *p & 0x3f;
+		p++;
+
+		if (high2 > 0) {
+			switch (high2) {
+			case DW_CFA_advance_loc:
+				pc += low6 * caf;
+#ifdef FRAME_DEBUG
+				printf("DW_CFA_advance_loc(%#jx(%u))\n", pc,
+				    low6);
+#endif
+				if (pc_req < pc)
+					goto program_done;
+				break;
+			case DW_CFA_offset:
+				*row_pc = pc;
+				CHECK_TABLE_SIZE(low6);
+				RL[low6].dw_offset_relevant = 1;
+				RL[low6].dw_value_type = DW_EXPR_OFFSET;
+				RL[low6].dw_regnum = dbg->dbg_frame_cfa_value;
+				RL[low6].dw_offset_or_block_len =
+				    _dwarf_decode_uleb128(&p) * daf;
+#ifdef FRAME_DEBUG
+				printf("DW_CFA_offset(%jd)\n",
+				    RL[low6].dw_offset_or_block_len);
+#endif
+				break;
+			case DW_CFA_restore:
+				*row_pc = pc;
+				CHECK_TABLE_SIZE(low6);
+				memcpy(&RL[low6], &INITRL[low6],
+				    sizeof(Dwarf_Regtable_Entry3));
+#ifdef FRAME_DEBUG
+				printf("DW_CFA_restore(%u)\n", low6);
+#endif
+				break;
+			default:
+				DWARF_SET_ERROR(dbg, error,
+				    DW_DLE_FRAME_INSTR_EXEC_ERROR);
+				ret = DW_DLE_FRAME_INSTR_EXEC_ERROR;
+				goto program_done;
+			}
+
+			continue;
+		}
+
+		switch (low6) {
+		case DW_CFA_set_loc:
+			pc = dbg->decode(&p, addr_size);
+#ifdef FRAME_DEBUG
+			printf("DW_CFA_set_loc(pc=%#jx)\n", pc);
+#endif
+			if (pc_req < pc)
+				goto program_done;
+			break;
+		case DW_CFA_advance_loc1:
+			pc += dbg->decode(&p, 1) * caf;
+#ifdef FRAME_DEBUG
+			printf("DW_CFA_set_loc1(pc=%#jx)\n", pc);
+#endif
+			if (pc_req < pc)
+				goto program_done;
+			break;
+		case DW_CFA_advance_loc2:
+			pc += dbg->decode(&p, 2) * caf;
+#ifdef FRAME_DEBUG
+			printf("DW_CFA_set_loc2(pc=%#jx)\n", pc);
+#endif
+			if (pc_req < pc)
+				goto program_done;
+			break;
+		case DW_CFA_advance_loc4:
+			pc += dbg->decode(&p, 4) * caf;
+#ifdef FRAME_DEBUG
+			printf("DW_CFA_set_loc4(pc=%#jx)\n", pc);
+#endif
+			if (pc_req < pc)
+				goto program_done;
+			break;
+		case DW_CFA_offset_extended:
+			*row_pc = pc;
+			reg = _dwarf_decode_uleb128(&p);
+			uoff = _dwarf_decode_uleb128(&p);
+			CHECK_TABLE_SIZE(reg);
+			RL[reg].dw_offset_relevant = 1;
+			RL[reg].dw_value_type = DW_EXPR_OFFSET;
+			RL[reg].dw_regnum = dbg->dbg_frame_cfa_value;
+			RL[reg].dw_offset_or_block_len = uoff * daf;
+#ifdef FRAME_DEBUG
+			printf("DW_CFA_offset_extended(reg=%ju,uoff=%ju)\n",
+			    reg, uoff);
+#endif
+			break;
+		case DW_CFA_restore_extended:
+			*row_pc = pc;
+			reg = _dwarf_decode_uleb128(&p);
+			CHECK_TABLE_SIZE(reg);
+			memcpy(&RL[reg], &INITRL[reg],
+			    sizeof(Dwarf_Regtable_Entry3));
+#ifdef FRAME_DEBUG
+			printf("DW_CFA_restore_extended(%ju)\n", reg);
+#endif
+			break;
+		case DW_CFA_undefined:
+			*row_pc = pc;
+			reg = _dwarf_decode_uleb128(&p);
+			CHECK_TABLE_SIZE(reg);
+			RL[reg].dw_offset_relevant = 0;
+			RL[reg].dw_regnum = dbg->dbg_frame_undefined_value;
+#ifdef FRAME_DEBUG
+			printf("DW_CFA_undefined(%ju)\n", reg);
+#endif
+			break;
+		case DW_CFA_same_value:
+			reg = _dwarf_decode_uleb128(&p);
+			CHECK_TABLE_SIZE(reg);
+			RL[reg].dw_offset_relevant = 0;
+			RL[reg].dw_regnum = dbg->dbg_frame_same_value;
+#ifdef FRAME_DEBUG
+			printf("DW_CFA_same_value(%ju)\n", reg);
+#endif
+			break;
+		case DW_CFA_register:
+			*row_pc = pc;
+			reg = _dwarf_decode_uleb128(&p);
+			reg2 = _dwarf_decode_uleb128(&p);
+			CHECK_TABLE_SIZE(reg);
+			RL[reg].dw_offset_relevant = 0;
+			RL[reg].dw_regnum = reg2;
+#ifdef FRAME_DEBUG
+			printf("DW_CFA_register(reg=%ju,reg2=%ju)\n", reg,
+			    reg2);
+#endif
+			break;
+		case DW_CFA_remember_state:
+			_dwarf_frame_regtable_copy(dbg, &saved_rt, rt, error);
+#ifdef FRAME_DEBUG
+			printf("DW_CFA_remember_state\n");
+#endif
+			break;
+		case DW_CFA_restore_state:
+			*row_pc = pc;
+			_dwarf_frame_regtable_copy(dbg, &rt, saved_rt, error);
+#ifdef FRAME_DEBUG
+			printf("DW_CFA_restore_state\n");
+#endif
+			break;
+		case DW_CFA_def_cfa:
+			*row_pc = pc;
+			reg = _dwarf_decode_uleb128(&p);
+			uoff = _dwarf_decode_uleb128(&p);
+			CFA.dw_offset_relevant = 1;
+			CFA.dw_value_type = DW_EXPR_OFFSET;
+			CFA.dw_regnum = reg;
+			CFA.dw_offset_or_block_len = uoff;
+#ifdef FRAME_DEBUG
+			printf("DW_CFA_def_cfa(reg=%ju,uoff=%ju)\n", reg, uoff);
+#endif
+			break;
+		case DW_CFA_def_cfa_register:
+			*row_pc = pc;
+			reg = _dwarf_decode_uleb128(&p);
+			CFA.dw_regnum = reg;
+			/*
+			 * Note that DW_CFA_def_cfa_register change the CFA
+			 * rule register while keep the old offset. So we
+			 * should not touch the CFA.dw_offset_relevant flag
+			 * here.
+			 */
+#ifdef FRAME_DEBUG
+			printf("DW_CFA_def_cfa_register(%ju)\n", reg);
+#endif
+			break;
+		case DW_CFA_def_cfa_offset:
+			*row_pc = pc;
+			uoff = _dwarf_decode_uleb128(&p);
+			CFA.dw_offset_relevant = 1;
+			CFA.dw_value_type = DW_EXPR_OFFSET;
+			CFA.dw_offset_or_block_len = uoff;
+#ifdef FRAME_DEBUG
+			printf("DW_CFA_def_cfa_offset(%ju)\n", uoff);
+#endif
+			break;
+		case DW_CFA_def_cfa_expression:
+			*row_pc = pc;
+			CFA.dw_offset_relevant = 0;
+			CFA.dw_value_type = DW_EXPR_EXPRESSION;
+			CFA.dw_offset_or_block_len = _dwarf_decode_uleb128(&p);
+			CFA.dw_block_ptr = p;
+			p += CFA.dw_offset_or_block_len;
+#ifdef FRAME_DEBUG
+			printf("DW_CFA_def_cfa_expression\n");
+#endif
+			break;
+		case DW_CFA_expression:
+			*row_pc = pc;
+			reg = _dwarf_decode_uleb128(&p);
+			CHECK_TABLE_SIZE(reg);
+			RL[reg].dw_offset_relevant = 0;
+			RL[reg].dw_value_type = DW_EXPR_EXPRESSION;
+			RL[reg].dw_offset_or_block_len =
+			    _dwarf_decode_uleb128(&p);
+			RL[reg].dw_block_ptr = p;
+			p += RL[reg].dw_offset_or_block_len;
+#ifdef FRAME_DEBUG
+			printf("DW_CFA_expression\n");
+#endif
+			break;
+		case DW_CFA_offset_extended_sf:
+			*row_pc = pc;
+			reg = _dwarf_decode_uleb128(&p);
+			soff = _dwarf_decode_sleb128(&p);
+			CHECK_TABLE_SIZE(reg);
+			RL[reg].dw_offset_relevant = 1;
+			RL[reg].dw_value_type = DW_EXPR_OFFSET;
+			RL[reg].dw_regnum = dbg->dbg_frame_cfa_value;
+			RL[reg].dw_offset_or_block_len = soff * daf;
+#ifdef FRAME_DEBUG
+			printf("DW_CFA_offset_extended_sf(reg=%ju,soff=%jd)\n",
+			    reg, soff);
+#endif
+			break;
+		case DW_CFA_def_cfa_sf:
+			*row_pc = pc;
+			reg = _dwarf_decode_uleb128(&p);
+			soff = _dwarf_decode_sleb128(&p);
+			CFA.dw_offset_relevant = 1;
+			CFA.dw_value_type = DW_EXPR_OFFSET;
+			CFA.dw_regnum = reg;
+			CFA.dw_offset_or_block_len = soff * daf;
+#ifdef FRAME_DEBUG
+			printf("DW_CFA_def_cfa_sf(reg=%ju,soff=%jd)\n", reg,
+			    soff);
+#endif
+			break;
+		case DW_CFA_def_cfa_offset_sf:
+			*row_pc = pc;
+			soff = _dwarf_decode_sleb128(&p);
+			CFA.dw_offset_relevant = 1;
+			CFA.dw_value_type = DW_EXPR_OFFSET;
+			CFA.dw_offset_or_block_len = soff * daf;
+#ifdef FRAME_DEBUG
+			printf("DW_CFA_def_cfa_offset_sf(soff=%jd)\n", soff);
+#endif
+			break;
+		case DW_CFA_val_offset:
+			*row_pc = pc;
+			reg = _dwarf_decode_uleb128(&p);
+			uoff = _dwarf_decode_uleb128(&p);
+			CHECK_TABLE_SIZE(reg);
+			RL[reg].dw_offset_relevant = 1;
+			RL[reg].dw_value_type = DW_EXPR_VAL_OFFSET;
+			RL[reg].dw_regnum = dbg->dbg_frame_cfa_value;
+			RL[reg].dw_offset_or_block_len = uoff * daf;
+#ifdef FRAME_DEBUG
+			printf("DW_CFA_val_offset(reg=%ju,uoff=%ju)\n", reg,
+			    uoff);
+#endif
+			break;
+		case DW_CFA_val_offset_sf:
+			*row_pc = pc;
+			reg = _dwarf_decode_uleb128(&p);
+			soff = _dwarf_decode_sleb128(&p);
+			CHECK_TABLE_SIZE(reg);
+			RL[reg].dw_offset_relevant = 1;
+			RL[reg].dw_value_type = DW_EXPR_VAL_OFFSET;
+			RL[reg].dw_regnum = dbg->dbg_frame_cfa_value;
+			RL[reg].dw_offset_or_block_len = soff * daf;
+#ifdef FRAME_DEBUG
+			printf("DW_CFA_val_offset_sf(reg=%ju,soff=%jd)\n", reg,
+			    soff);
+#endif
+			break;
+		case DW_CFA_val_expression:
+			*row_pc = pc;
+			reg = _dwarf_decode_uleb128(&p);
+			CHECK_TABLE_SIZE(reg);
+			RL[reg].dw_offset_relevant = 0;
+			RL[reg].dw_value_type = DW_EXPR_VAL_EXPRESSION;
+			RL[reg].dw_offset_or_block_len =
+			    _dwarf_decode_uleb128(&p);
+			RL[reg].dw_block_ptr = p;
+			p += RL[reg].dw_offset_or_block_len;
+#ifdef FRAME_DEBUG
+			printf("DW_CFA_val_expression\n");
+#endif
+			break;
+		default:
+			DWARF_SET_ERROR(dbg, error,
+			    DW_DLE_FRAME_INSTR_EXEC_ERROR);
+			ret = DW_DLE_FRAME_INSTR_EXEC_ERROR;
+			goto program_done;
+		}
+	}
+
+program_done:
+
+	free(init_rt->rt3_rules);
+	free(init_rt);
+	if (saved_rt) {
+		free(saved_rt->rt3_rules);
+		free(saved_rt);
+	}
+
+	return (ret);
+
+#undef	CFA
+#undef	INITCFA
+#undef	RL
+#undef	INITRL
+#undef	CHECK_TABLE_SIZE
+}
+
+static int
+_dwarf_frame_convert_inst(Dwarf_Debug dbg, uint8_t addr_size, uint8_t *insts,
+    Dwarf_Unsigned len, Dwarf_Unsigned *count, Dwarf_Frame_Op *fop,
+    Dwarf_Frame_Op3 *fop3, Dwarf_Error *error)
+{
+	uint8_t *p, *pe;
+	uint8_t high2, low6;
+	uint64_t reg, reg2, uoff, soff, blen;
+
+#define	SET_BASE_OP(x)						\
+	do {							\
+		if (fop != NULL)				\
+			fop[*count].fp_base_op = (x) >> 6;	\
+		if (fop3 != NULL)				\
+			fop3[*count].fp_base_op = (x) >> 6;	\
+	} while(0)
+
+#define	SET_EXTENDED_OP(x)					\
+	do {							\
+		if (fop != NULL)				\
+			fop[*count].fp_extended_op = (x);	\
+		if (fop3 != NULL)				\
+			fop3[*count].fp_extended_op = (x);	\
+	} while(0)
+
+#define	SET_REGISTER(x)						\
+	do {							\
+		if (fop != NULL)				\
+			fop[*count].fp_register = (x);		\
+		if (fop3 != NULL)				\
+			fop3[*count].fp_register = (x);		\
+	} while(0)
+
+#define	SET_OFFSET(x)						\
+	do {							\
+		if (fop != NULL)				\
+			fop[*count].fp_offset = (x);		\
+		if (fop3 != NULL)				\
+			fop3[*count].fp_offset_or_block_len =	\
+			    (x);				\
+	} while(0)
+
+#define	SET_INSTR_OFFSET(x)					\
+	do {							\
+		if (fop != NULL)				\
+			fop[*count].fp_instr_offset = (x);	\
+		if (fop3 != NULL)				\
+			fop3[*count].fp_instr_offset = (x);	\
+	} while(0)
+
+#define	SET_BLOCK_LEN(x)					\
+	do {							\
+		if (fop3 != NULL)				\
+			fop3[*count].fp_offset_or_block_len =	\
+			    (x);				\
+	} while(0)
+
+#define	SET_EXPR_BLOCK(addr, len)					\
+	do {								\
+		if (fop3 != NULL) {					\
+			fop3[*count].fp_expr_block =			\
+			    malloc((size_t) (len));			\
+			if (fop3[*count].fp_expr_block == NULL)	{	\
+				DWARF_SET_ERROR(dbg, error,		\
+				    DW_DLE_MEMORY);			\
+				return (DW_DLE_MEMORY);			\
+			}						\
+			memcpy(&fop3[*count].fp_expr_block,		\
+			    (addr), (len));				\
+		}							\
+	} while(0)
+
+	*count = 0;
+
+	p = insts;
+	pe = p + len;
+
+	while (p < pe) {
+
+		SET_INSTR_OFFSET(p - insts);
+
+		if (*p == DW_CFA_nop) {
+			p++;
+			(*count)++;
+			continue;
+		}
+
+		high2 = *p & 0xc0;
+		low6 = *p & 0x3f;
+		p++;
+
+		if (high2 > 0) {
+			switch (high2) {
+			case DW_CFA_advance_loc:
+				SET_BASE_OP(high2);
+				SET_OFFSET(low6);
+				break;
+			case DW_CFA_offset:
+				SET_BASE_OP(high2);
+				SET_REGISTER(low6);
+				uoff = _dwarf_decode_uleb128(&p);
+				SET_OFFSET(uoff);
+				break;
+			case DW_CFA_restore:
+				SET_BASE_OP(high2);
+				SET_REGISTER(low6);
+				break;
+			default:
+				DWARF_SET_ERROR(dbg, error,
+				    DW_DLE_FRAME_INSTR_EXEC_ERROR);
+				return (DW_DLE_FRAME_INSTR_EXEC_ERROR);
+			}
+
+			(*count)++;
+			continue;
+		}
+
+		SET_EXTENDED_OP(low6);
+
+		switch (low6) {
+		case DW_CFA_set_loc:
+			uoff = dbg->decode(&p, addr_size);
+			SET_OFFSET(uoff);
+			break;
+		case DW_CFA_advance_loc1:
+			uoff = dbg->decode(&p, 1);
+			SET_OFFSET(uoff);
+			break;
+		case DW_CFA_advance_loc2:
+			uoff = dbg->decode(&p, 2);
+			SET_OFFSET(uoff);
+			break;
+		case DW_CFA_advance_loc4:
+			uoff = dbg->decode(&p, 4);
+			SET_OFFSET(uoff);
+			break;
+		case DW_CFA_offset_extended:
+		case DW_CFA_def_cfa:
+		case DW_CFA_val_offset:
+			reg = _dwarf_decode_uleb128(&p);
+			uoff = _dwarf_decode_uleb128(&p);
+			SET_REGISTER(reg);
+			SET_OFFSET(uoff);
+			break;
+		case DW_CFA_restore_extended:
+		case DW_CFA_undefined:
+		case DW_CFA_same_value:
+		case DW_CFA_def_cfa_register:
+			reg = _dwarf_decode_uleb128(&p);
+			SET_REGISTER(reg);
+			break;
+		case DW_CFA_register:
+			reg = _dwarf_decode_uleb128(&p);
+			reg2 = _dwarf_decode_uleb128(&p);
+			SET_REGISTER(reg);
+			SET_OFFSET(reg2);
+			break;
+		case DW_CFA_remember_state:
+		case DW_CFA_restore_state:
+			break;
+		case DW_CFA_def_cfa_offset:
+			uoff = _dwarf_decode_uleb128(&p);
+			SET_OFFSET(uoff);
+			break;
+		case DW_CFA_def_cfa_expression:
+			blen = _dwarf_decode_uleb128(&p);
+			SET_BLOCK_LEN(blen);
+			SET_EXPR_BLOCK(p, blen);
+			p += blen;
+			break;
+		case DW_CFA_expression:
+		case DW_CFA_val_expression:
+			reg = _dwarf_decode_uleb128(&p);
+			blen = _dwarf_decode_uleb128(&p);
+			SET_REGISTER(reg);
+			SET_BLOCK_LEN(blen);
+			SET_EXPR_BLOCK(p, blen);
+			p += blen;
+			break;
+		case DW_CFA_offset_extended_sf:
+		case DW_CFA_def_cfa_sf:
+		case DW_CFA_val_offset_sf:
+			reg = _dwarf_decode_uleb128(&p);
+			soff = _dwarf_decode_sleb128(&p);
+			SET_REGISTER(reg);
+			SET_OFFSET(soff);
+			break;
+		case DW_CFA_def_cfa_offset_sf:
+			soff = _dwarf_decode_sleb128(&p);
+			SET_OFFSET(soff);
+			break;
+		default:
+			DWARF_SET_ERROR(dbg, error,
+			    DW_DLE_FRAME_INSTR_EXEC_ERROR);
+			return (DW_DLE_FRAME_INSTR_EXEC_ERROR);
+		}
+
+		(*count)++;
+	}
+
+	return (DW_DLE_NONE);
+}
+
+int
+_dwarf_frame_get_fop(Dwarf_Debug dbg, uint8_t addr_size, uint8_t *insts,
+    Dwarf_Unsigned len, Dwarf_Frame_Op **ret_oplist, Dwarf_Signed *ret_opcnt,
+    Dwarf_Error *error)
+{
+	Dwarf_Frame_Op *oplist;
+	Dwarf_Unsigned count;
+	int ret;
+
+	ret = _dwarf_frame_convert_inst(dbg, addr_size, insts, len, &count,
+	    NULL, NULL, error);
+	if (ret != DW_DLE_NONE)
+		return (ret);
+
+	if ((oplist = calloc(count, sizeof(Dwarf_Frame_Op))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+
+	ret = _dwarf_frame_convert_inst(dbg, addr_size, insts, len, &count,
+	    oplist, NULL, error);
+	if (ret != DW_DLE_NONE) {
+		free(oplist);
+		return (ret);
+	}
+
+	*ret_oplist = oplist;
+	*ret_opcnt = count;
+
+	return (DW_DLE_NONE);
+}
+
+int
+_dwarf_frame_regtable_copy(Dwarf_Debug dbg, Dwarf_Regtable3 **dest,
+    Dwarf_Regtable3 *src, Dwarf_Error *error)
+{
+	int i;
+
+	assert(dest != NULL);
+	assert(src != NULL);
+
+	if (*dest == NULL) {
+		if ((*dest = malloc(sizeof(Dwarf_Regtable3))) == NULL) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+			return (DW_DLE_MEMORY);
+		}
+		(*dest)->rt3_reg_table_size = src->rt3_reg_table_size;
+		(*dest)->rt3_rules = malloc(src->rt3_reg_table_size *
+		    sizeof(Dwarf_Regtable_Entry3));
+		if ((*dest)->rt3_rules == NULL) {
+			free(*dest);
+			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+			return (DW_DLE_MEMORY);
+		}
+	}
+
+	memcpy(&(*dest)->rt3_cfa_rule, &src->rt3_cfa_rule,
+	    sizeof(Dwarf_Regtable_Entry3));
+
+	for (i = 0; i < (*dest)->rt3_reg_table_size &&
+	     i < src->rt3_reg_table_size; i++)
+		memcpy(&(*dest)->rt3_rules[i], &src->rt3_rules[i],
+		    sizeof(Dwarf_Regtable_Entry3));
+
+	for (; i < (*dest)->rt3_reg_table_size; i++)
+		(*dest)->rt3_rules[i].dw_regnum =
+		    dbg->dbg_frame_undefined_value;
+
+	return (DW_DLE_NONE);
+}
+
+int
+_dwarf_frame_get_internal_table(Dwarf_Fde fde, Dwarf_Addr pc_req,
+    Dwarf_Regtable3 **ret_rt, Dwarf_Addr *ret_row_pc, Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+	Dwarf_Cie cie;
+	Dwarf_Regtable3 *rt;
+	Dwarf_Addr row_pc;
+	int i, ret;
+
+	assert(ret_rt != NULL);
+
+	dbg = fde->fde_dbg;
+	assert(dbg != NULL);
+
+	rt = dbg->dbg_internal_reg_table;
+
+	/* Clear the content of regtable from previous run. */
+	memset(&rt->rt3_cfa_rule, 0, sizeof(Dwarf_Regtable_Entry3));
+	memset(rt->rt3_rules, 0, rt->rt3_reg_table_size *
+	    sizeof(Dwarf_Regtable_Entry3));
+
+	/* Set rules to initial values. */
+	for (i = 0; i < rt->rt3_reg_table_size; i++)
+		rt->rt3_rules[i].dw_regnum = dbg->dbg_frame_rule_initial_value;
+
+	/* Run initial instructions in CIE. */
+	cie = fde->fde_cie;
+	assert(cie != NULL);
+	ret = _dwarf_frame_run_inst(dbg, rt, cie->cie_addrsize,
+	    cie->cie_initinst, cie->cie_instlen, cie->cie_caf, cie->cie_daf, 0,
+	    ~0ULL, &row_pc, error);
+	if (ret != DW_DLE_NONE)
+		return (ret);
+
+	/* Run instructions in FDE. */
+	if (pc_req >= fde->fde_initloc) {
+		ret = _dwarf_frame_run_inst(dbg, rt, cie->cie_addrsize,
+		    fde->fde_inst, fde->fde_instlen, cie->cie_caf,
+		    cie->cie_daf, fde->fde_initloc, pc_req, &row_pc, error);
+		if (ret != DW_DLE_NONE)
+			return (ret);
+	}
+
+	*ret_rt = rt;
+	*ret_row_pc = row_pc;
+
+	return (DW_DLE_NONE);
+}
+
+void
+_dwarf_frame_cleanup(Dwarf_Debug dbg)
+{
+	Dwarf_Regtable3 *rt;
+
+	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_READ);
+
+	if (dbg->dbg_internal_reg_table) {
+		rt = dbg->dbg_internal_reg_table;
+		free(rt->rt3_rules);
+		free(rt);
+		dbg->dbg_internal_reg_table = NULL;
+	}
+
+	if (dbg->dbg_frame) {
+		_dwarf_frame_section_cleanup(dbg->dbg_frame);
+		dbg->dbg_frame = NULL;
+	}
+
+	if (dbg->dbg_eh_frame) {
+		_dwarf_frame_section_cleanup(dbg->dbg_eh_frame);
+		dbg->dbg_eh_frame = NULL;
+	}
+}
+
+int
+_dwarf_frame_section_load(Dwarf_Debug dbg, Dwarf_Error *error)
+{
+	Dwarf_Section *ds;
+
+	if ((ds = _dwarf_find_section(dbg, ".debug_frame")) != NULL) {
+		return (_dwarf_frame_section_init(dbg, &dbg->dbg_frame,
+		    ds, 0, error));
+	}
+
+	return (DW_DLE_NONE);
+}
+
+int
+_dwarf_frame_section_load_eh(Dwarf_Debug dbg, Dwarf_Error *error)
+{
+	Dwarf_Section *ds;
+
+	if ((ds = _dwarf_find_section(dbg, ".eh_frame")) != NULL) {
+		return (_dwarf_frame_section_init(dbg, &dbg->dbg_eh_frame,
+		    ds, 1, error));
+	}
+
+	return (DW_DLE_NONE);
+}
+
+void
+_dwarf_frame_params_init(Dwarf_Debug dbg)
+{
+
+	/* Initialise call frame related parameters. */
+	dbg->dbg_frame_rule_table_size = DW_FRAME_LAST_REG_NUM;
+	dbg->dbg_frame_rule_initial_value = DW_FRAME_REG_INITIAL_VALUE;
+	dbg->dbg_frame_cfa_value = DW_FRAME_CFA_COL3;
+	dbg->dbg_frame_same_value = DW_FRAME_SAME_VAL;
+	dbg->dbg_frame_undefined_value = DW_FRAME_UNDEFINED_VAL;
+}
+
+int
+_dwarf_frame_interal_table_init(Dwarf_Debug dbg, Dwarf_Error *error)
+{
+	Dwarf_Regtable3 *rt;
+
+	if (dbg->dbg_internal_reg_table != NULL)
+		return (DW_DLE_NONE);
+
+	/* Initialise internal register table. */
+	if ((rt = calloc(1, sizeof(Dwarf_Regtable3))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+
+	rt->rt3_reg_table_size = dbg->dbg_frame_rule_table_size;
+	if ((rt->rt3_rules = calloc(rt->rt3_reg_table_size,
+	    sizeof(Dwarf_Regtable_Entry3))) == NULL) {
+		free(rt);
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+
+	dbg->dbg_internal_reg_table = rt;
+
+	return (DW_DLE_NONE);
+}
+
+#define	_FDE_INST_INIT_SIZE	128
+
+int
+_dwarf_frame_fde_add_inst(Dwarf_P_Fde fde, Dwarf_Small op, Dwarf_Unsigned val1,
+    Dwarf_Unsigned val2, Dwarf_Error *error)
+{
+	Dwarf_P_Debug dbg;
+	uint8_t high2, low6;
+	int ret;
+
+#define	ds	fde
+#define	ds_data	fde_inst
+#define	ds_cap	fde_instcap
+#define	ds_size	fde_instlen
+
+	assert(fde != NULL && fde->fde_dbg != NULL);
+	dbg = fde->fde_dbg;
+
+	if (fde->fde_inst == NULL) {
+		fde->fde_instcap = _FDE_INST_INIT_SIZE;
+		fde->fde_instlen = 0;
+		if ((fde->fde_inst = malloc((size_t) fde->fde_instcap)) ==
+		    NULL) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+			return (DW_DLE_MEMORY);
+		}
+	}
+	assert(fde->fde_instcap != 0);
+
+	RCHECK(WRITE_VALUE(op, 1));
+	if (op == DW_CFA_nop)
+		return (DW_DLE_NONE);
+
+	high2 = op & 0xc0;
+	low6 = op & 0x3f;
+
+	if (high2 > 0) {
+		switch (high2) {
+		case DW_CFA_advance_loc:
+		case DW_CFA_restore:
+			break;
+		case DW_CFA_offset:
+			RCHECK(WRITE_ULEB128(val1));
+			break;
+		default:
+			DWARF_SET_ERROR(dbg, error,
+			    DW_DLE_FRAME_INSTR_EXEC_ERROR);
+			return (DW_DLE_FRAME_INSTR_EXEC_ERROR);
+		}
+		return (DW_DLE_NONE);
+	}
+
+	switch (low6) {
+	case DW_CFA_set_loc:
+		RCHECK(WRITE_VALUE(val1, dbg->dbg_pointer_size));
+		break;
+	case DW_CFA_advance_loc1:
+		RCHECK(WRITE_VALUE(val1, 1));
+		break;
+	case DW_CFA_advance_loc2:
+		RCHECK(WRITE_VALUE(val1, 2));
+		break;
+	case DW_CFA_advance_loc4:
+		RCHECK(WRITE_VALUE(val1, 4));
+		break;
+	case DW_CFA_offset_extended:
+	case DW_CFA_def_cfa:
+	case DW_CFA_register:
+		RCHECK(WRITE_ULEB128(val1));
+		RCHECK(WRITE_ULEB128(val2));
+		break;
+	case DW_CFA_restore_extended:
+	case DW_CFA_undefined:
+	case DW_CFA_same_value:
+	case DW_CFA_def_cfa_register:
+	case DW_CFA_def_cfa_offset:
+		RCHECK(WRITE_ULEB128(val1));
+		break;
+	case DW_CFA_remember_state:
+	case DW_CFA_restore_state:
+		break;
+	default:
+		DWARF_SET_ERROR(dbg, error, DW_DLE_FRAME_INSTR_EXEC_ERROR);
+		return (DW_DLE_FRAME_INSTR_EXEC_ERROR);
+	}
+
+	return (DW_DLE_NONE);
+
+gen_fail:
+	return (ret);
+
+#undef	ds
+#undef	ds_data
+#undef	ds_cap
+#undef	ds_size
+}
+
+static int
+_dwarf_frame_gen_cie(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_P_Cie cie,
+    Dwarf_Error *error)
+{
+	Dwarf_Unsigned len;
+	uint64_t offset;
+	int ret;
+
+	assert(dbg != NULL && ds != NULL && cie != NULL);
+
+	cie->cie_offset = offset = ds->ds_size;
+	cie->cie_length = 0;
+	cie->cie_version = 1;
+
+	/* Length placeholder. */
+	RCHECK(WRITE_VALUE(cie->cie_length, 4));
+
+	/* .debug_frame use CIE id ~0. */
+	RCHECK(WRITE_VALUE(~0U, 4));
+
+	/* .debug_frame version is 1. (DWARF2) */
+	RCHECK(WRITE_VALUE(cie->cie_version, 1));
+
+	/* Write augmentation, if present. */
+	if (cie->cie_augment != NULL)
+		RCHECK(WRITE_BLOCK(cie->cie_augment,
+		    strlen((char *) cie->cie_augment) + 1));
+	else
+		RCHECK(WRITE_VALUE(0, 1));
+
+	/* Write caf, daf and ra. */
+	RCHECK(WRITE_ULEB128(cie->cie_caf));
+	RCHECK(WRITE_SLEB128(cie->cie_daf));
+	RCHECK(WRITE_VALUE(cie->cie_ra, 1));
+
+	/* Write initial instructions, if present. */
+	if (cie->cie_initinst != NULL)
+		RCHECK(WRITE_BLOCK(cie->cie_initinst, cie->cie_instlen));
+
+	/* Add padding. */
+	len = ds->ds_size - cie->cie_offset - 4;
+	cie->cie_length = roundup(len, dbg->dbg_pointer_size);
+	while (len++ < cie->cie_length)
+		RCHECK(WRITE_VALUE(DW_CFA_nop, 1));
+
+	/* Fill in the length field. */
+	dbg->write(ds->ds_data, &offset, cie->cie_length, 4);
+	
+	return (DW_DLE_NONE);
+
+gen_fail:
+	return (ret);
+}
+
+static int
+_dwarf_frame_gen_fde(Dwarf_P_Debug dbg, Dwarf_P_Section ds,
+    Dwarf_Rel_Section drs, Dwarf_P_Fde fde, Dwarf_Error *error)
+{
+	Dwarf_Unsigned len;
+	uint64_t offset;
+	int ret;
+
+	assert(dbg != NULL && ds != NULL && drs != NULL);
+	assert(fde != NULL && fde->fde_cie != NULL);
+
+	fde->fde_offset = offset = ds->ds_size;
+	fde->fde_length = 0;
+	fde->fde_cieoff = fde->fde_cie->cie_offset;
+
+	/* Length placeholder. */
+	RCHECK(WRITE_VALUE(fde->fde_length, 4));
+
+	/* Write CIE pointer. */
+	RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc, 4,
+	    ds->ds_size, 0, fde->fde_cieoff, ".debug_frame", error));
+
+	/* Write FDE initial location. */
+	RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc,
+	    dbg->dbg_pointer_size, ds->ds_size, fde->fde_symndx,
+	    fde->fde_initloc, NULL, error));
+
+	/*
+	 * Write FDE address range. Use a pair of relocation entries if
+	 * application provided end symbol index. Otherwise write the
+	 * length without assoicating any relocation info.
+	 */
+	if (fde->fde_esymndx > 0)
+		RCHECK(_dwarf_reloc_entry_add_pair(dbg, drs, ds,
+		    dbg->dbg_pointer_size, ds->ds_size, fde->fde_symndx,
+		    fde->fde_esymndx, fde->fde_initloc, fde->fde_eoff, error));
+	else
+		RCHECK(WRITE_VALUE(fde->fde_adrange, dbg->dbg_pointer_size));
+
+	/* Write FDE frame instructions. */
+	RCHECK(WRITE_BLOCK(fde->fde_inst, fde->fde_instlen));
+
+	/* Add padding. */
+	len = ds->ds_size - fde->fde_offset - 4;
+	fde->fde_length = roundup(len, dbg->dbg_pointer_size);
+	while (len++ < fde->fde_length)
+		RCHECK(WRITE_VALUE(DW_CFA_nop, 1));
+
+	/* Fill in the length field. */
+	dbg->write(ds->ds_data, &offset, fde->fde_length, 4);
+
+	return (DW_DLE_NONE);
+
+gen_fail:
+	return (ret);
+}
+
+int
+_dwarf_frame_gen(Dwarf_P_Debug dbg, Dwarf_Error *error)
+{
+	Dwarf_P_Section ds;
+	Dwarf_Rel_Section drs;
+	Dwarf_P_Cie cie;
+	Dwarf_P_Fde fde;
+	int ret;
+
+	if (STAILQ_EMPTY(&dbg->dbgp_cielist))
+		return (DW_DLE_NONE);
+
+	/* Create .debug_frame section. */
+	if ((ret = _dwarf_section_init(dbg, &ds, ".debug_frame", 0, error)) !=
+	    DW_DLE_NONE)
+		goto gen_fail0;
+
+	/* Create relocation section for .debug_frame */
+	RCHECK(_dwarf_reloc_section_init(dbg, &drs, ds, error));
+
+	/* Generate list of CIE. */
+	STAILQ_FOREACH(cie, &dbg->dbgp_cielist, cie_next)
+		RCHECK(_dwarf_frame_gen_cie(dbg, ds, cie, error));
+
+	/* Generate list of FDE. */
+	STAILQ_FOREACH(fde, &dbg->dbgp_fdelist, fde_next)
+		RCHECK(_dwarf_frame_gen_fde(dbg, ds, drs, fde, error));
+
+	/* Inform application the creation of .debug_frame ELF section. */
+	RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error));
+
+	/* Finalize relocation section for .debug_frame */
+	RCHECK(_dwarf_reloc_section_finalize(dbg, drs, error));
+
+	return (DW_DLE_NONE);
+
+gen_fail:
+	_dwarf_reloc_section_free(dbg, &drs);
+
+gen_fail0:
+	_dwarf_section_free(dbg, &ds);
+
+	return (ret);
+}
+
+void
+_dwarf_frame_pro_cleanup(Dwarf_P_Debug dbg)
+{
+	Dwarf_P_Cie cie, tcie;
+	Dwarf_P_Fde fde, tfde;
+
+	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
+
+	STAILQ_FOREACH_SAFE(cie, &dbg->dbgp_cielist, cie_next, tcie) {
+		STAILQ_REMOVE(&dbg->dbgp_cielist, cie, _Dwarf_Cie, cie_next);
+		if (cie->cie_augment)
+			free(cie->cie_augment);
+		if (cie->cie_initinst)
+			free(cie->cie_initinst);
+		free(cie);
+	}
+	dbg->dbgp_cielen = 0;
+
+	STAILQ_FOREACH_SAFE(fde, &dbg->dbgp_fdelist, fde_next, tfde) {
+		STAILQ_REMOVE(&dbg->dbgp_fdelist, fde, _Dwarf_Fde, fde_next);
+		if (fde->fde_inst != NULL)
+			free(fde->fde_inst);
+		free(fde);
+	}
+	dbg->dbgp_fdelen = 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/libdwarf_info.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,383 @@
+/*-
+ * Copyright (c) 2007 John Birrell (jb@freebsd.org)
+ * Copyright (c) 2010,2011,2014 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: libdwarf_info.c 3136 2014-12-24 16:04:38Z kaiwang27 $");
+
+int
+_dwarf_info_first_cu(Dwarf_Debug dbg, Dwarf_Error *error)
+{
+	Dwarf_CU cu;
+	int ret;
+
+	assert(dbg->dbg_cu_current == NULL);
+	cu = STAILQ_FIRST(&dbg->dbg_cu);
+	if (cu != NULL) {
+		dbg->dbg_cu_current = cu;
+		return (DW_DLE_NONE);
+	}
+
+	if (dbg->dbg_info_loaded)
+		return (DW_DLE_NO_ENTRY);
+
+	dbg->dbg_info_off = 0;
+	ret = _dwarf_info_load(dbg, 0, 1, error);
+	if (ret != DW_DLE_NONE)
+		return (ret);
+
+	dbg->dbg_cu_current = STAILQ_FIRST(&dbg->dbg_cu);
+
+	return (DW_DLE_NONE);
+}
+
+int
+_dwarf_info_first_tu(Dwarf_Debug dbg, Dwarf_Error *error)
+{
+	Dwarf_CU tu;
+	int ret;
+
+	assert(dbg->dbg_tu_current == NULL);
+	tu = STAILQ_FIRST(&dbg->dbg_tu);
+	if (tu != NULL) {
+		dbg->dbg_tu_current = tu;
+		return (DW_DLE_NONE);
+	}
+
+	if (dbg->dbg_types_loaded)
+		return (DW_DLE_NO_ENTRY);
+
+	dbg->dbg_types_off = 0;
+	ret = _dwarf_info_load(dbg, 0, 0, error);
+	if (ret != DW_DLE_NONE)
+		return (ret);
+
+	dbg->dbg_tu_current = STAILQ_FIRST(&dbg->dbg_tu);
+
+	return (DW_DLE_NONE);
+}
+
+int
+_dwarf_info_next_cu(Dwarf_Debug dbg, Dwarf_Error *error)
+{
+	Dwarf_CU cu;
+	int ret;
+
+	assert(dbg->dbg_cu_current != NULL);
+	cu = STAILQ_NEXT(dbg->dbg_cu_current, cu_next);
+	if (cu != NULL) {
+		dbg->dbg_cu_current = cu;
+		return (DW_DLE_NONE);
+	}
+
+	if (dbg->dbg_info_loaded) {
+		dbg->dbg_cu_current = NULL;
+		return (DW_DLE_NO_ENTRY);
+	}
+
+	ret = _dwarf_info_load(dbg, 0, 1, error);
+	if (ret != DW_DLE_NONE)
+		return (ret);
+
+	dbg->dbg_cu_current = STAILQ_NEXT(dbg->dbg_cu_current, cu_next);
+
+	return (DW_DLE_NONE);
+}
+
+int
+_dwarf_info_next_tu(Dwarf_Debug dbg, Dwarf_Error *error)
+{
+	Dwarf_CU cu;
+	int ret;
+
+	assert(dbg->dbg_tu_current != NULL);
+	cu = STAILQ_NEXT(dbg->dbg_tu_current, cu_next);
+	if (cu != NULL) {
+		dbg->dbg_tu_current = cu;
+		return (DW_DLE_NONE);
+	}
+
+	if (dbg->dbg_types_loaded) {
+		dbg->dbg_tu_current = NULL;
+		return (DW_DLE_NO_ENTRY);
+	}
+
+	ret = _dwarf_info_load(dbg, 0, 0, error);
+	if (ret != DW_DLE_NONE)
+		return (ret);
+
+	dbg->dbg_tu_current = STAILQ_NEXT(dbg->dbg_tu_current, cu_next);
+
+	return (DW_DLE_NONE);
+}
+
+int
+_dwarf_info_load(Dwarf_Debug dbg, Dwarf_Bool load_all, Dwarf_Bool is_info,
+    Dwarf_Error *error)
+{
+	Dwarf_CU cu;
+	Dwarf_Section *ds;
+	int dwarf_size, ret;
+	uint64_t length;
+	uint64_t next_offset;
+	uint64_t offset;
+
+	ret = DW_DLE_NONE;
+
+	if (is_info) {
+		if (dbg->dbg_info_loaded)
+			return (ret);
+		offset = dbg->dbg_info_off;
+		ds = dbg->dbg_info_sec;
+		if (ds == NULL)
+			return (DW_DLE_NO_ENTRY);
+	} else {
+		if (dbg->dbg_types_loaded)
+			return (ret);
+		offset = dbg->dbg_types_off;
+		ds = dbg->dbg_types_sec;
+		if (ds == NULL)
+			return (DW_DLE_NO_ENTRY);
+	}
+
+	while (offset < ds->ds_size) {
+		if ((cu = calloc(1, sizeof(struct _Dwarf_CU))) == NULL) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+			return (DW_DLE_MEMORY);
+		}
+
+		cu->cu_dbg = dbg;
+		cu->cu_is_info = is_info;
+		cu->cu_offset = offset;
+
+		length = dbg->read(ds->ds_data, &offset, 4);
+		if (length == 0xffffffff) {
+			length = dbg->read(ds->ds_data, &offset, 8);
+			dwarf_size = 8;
+		} else
+			dwarf_size = 4;
+		cu->cu_dwarf_size = dwarf_size;
+
+		/*
+		 * Check if there is enough ELF data for this CU. This assumes
+		 * that libelf gives us the entire section in one Elf_Data
+		 * object.
+		 */
+		if (length > ds->ds_size - offset) {
+			free(cu);
+			DWARF_SET_ERROR(dbg, error, DW_DLE_CU_LENGTH_ERROR);
+			return (DW_DLE_CU_LENGTH_ERROR);
+		}
+
+		/* Compute the offset to the next compilation unit: */
+		next_offset = offset + length;
+		if (is_info)
+			dbg->dbg_info_off = next_offset;
+		else
+			dbg->dbg_types_off = next_offset;
+
+		/* Initialise the compilation unit. */
+		cu->cu_length		 = length;
+		cu->cu_length_size	 = (dwarf_size == 4 ? 4 : 12);
+		cu->cu_version		 = dbg->read(ds->ds_data, &offset, 2);
+		cu->cu_abbrev_offset	 = dbg->read(ds->ds_data, &offset,
+		    dwarf_size);
+		cu->cu_abbrev_offset_cur = cu->cu_abbrev_offset;
+		cu->cu_pointer_size	 = dbg->read(ds->ds_data, &offset, 1);
+		cu->cu_next_offset	 = next_offset;
+
+		/* .debug_types extra fields. */
+		if (!is_info) {
+			memcpy(cu->cu_type_sig.signature,
+			    (char *) ds->ds_data + offset, 8);
+			offset += 8;
+			cu->cu_type_offset = dbg->read(ds->ds_data, &offset,
+			    dwarf_size);
+		}
+
+		/* Add the compilation unit to the list. */
+		if (is_info)
+			STAILQ_INSERT_TAIL(&dbg->dbg_cu, cu, cu_next);
+		else
+			STAILQ_INSERT_TAIL(&dbg->dbg_tu, cu, cu_next);
+
+		if (cu->cu_version < 2 || cu->cu_version > 4) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
+			ret = DW_DLE_VERSION_STAMP_ERROR;
+			break;
+		}
+
+		cu->cu_1st_offset = offset;
+
+		offset = next_offset;
+
+		if (!load_all)
+			break;
+	}
+
+	if (is_info) {
+		if ((Dwarf_Unsigned) dbg->dbg_info_off >= ds->ds_size)
+			dbg->dbg_info_loaded = 1;
+	} else {
+		if ((Dwarf_Unsigned) dbg->dbg_types_off >= ds->ds_size)
+			dbg->dbg_types_loaded = 1;
+	}
+
+	return (ret);
+}
+
+void
+_dwarf_info_cleanup(Dwarf_Debug dbg)
+{
+	Dwarf_CU cu, tcu;
+
+	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_READ);
+
+	STAILQ_FOREACH_SAFE(cu, &dbg->dbg_cu, cu_next, tcu) {
+		STAILQ_REMOVE(&dbg->dbg_cu, cu, _Dwarf_CU, cu_next);
+		_dwarf_abbrev_cleanup(cu);
+		if (cu->cu_lineinfo != NULL) {
+			_dwarf_lineno_cleanup(cu->cu_lineinfo);
+			cu->cu_lineinfo = NULL;
+		}
+		free(cu);
+	}
+
+	_dwarf_type_unit_cleanup(dbg);
+}
+
+void
+_dwarf_type_unit_cleanup(Dwarf_Debug dbg)
+{
+	Dwarf_CU cu, tcu;
+
+	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_READ);
+
+	STAILQ_FOREACH_SAFE(cu, &dbg->dbg_tu, cu_next, tcu) {
+		STAILQ_REMOVE(&dbg->dbg_tu, cu, _Dwarf_CU, cu_next);
+		_dwarf_abbrev_cleanup(cu);
+		free(cu);
+	}
+}
+
+int
+_dwarf_info_gen(Dwarf_P_Debug dbg, Dwarf_Error *error)
+{
+	Dwarf_P_Section ds;
+	Dwarf_Rel_Section drs;
+	Dwarf_Unsigned offset;
+	Dwarf_CU cu;
+	int ret;
+
+	assert(dbg != NULL && dbg->write_alloc != NULL);
+
+	if (dbg->dbgp_root_die == NULL)
+		return (DW_DLE_NONE);
+
+	/* Create the single CU for this debugging object. */
+	if ((cu = calloc(1, sizeof(struct _Dwarf_CU))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+	cu->cu_dbg = dbg;
+	cu->cu_version = 2;	/* DWARF2 */
+	cu->cu_pointer_size = dbg->dbg_pointer_size;
+	STAILQ_INSERT_TAIL(&dbg->dbg_cu, cu, cu_next);
+
+	/* Create .debug_info section. */
+	if ((ret = _dwarf_section_init(dbg, &dbg->dbgp_info, ".debug_info", 0,
+	    error)) != DW_DLE_NONE)
+		goto gen_fail1;
+	ds = dbg->dbgp_info;
+
+	/* Create relocation section for .debug_init */
+	if ((ret = _dwarf_reloc_section_init(dbg, &drs, ds, error)) !=
+	    DW_DLE_NONE)
+		goto gen_fail0;
+
+	/* Length placeholder. (We only use 32-bit DWARF format) */
+	RCHECK(WRITE_VALUE(cu->cu_length, 4));
+
+	/* Write CU version */
+	RCHECK(WRITE_VALUE(cu->cu_version, 2));
+
+	/*
+	 * Write abbrev offset. (always 0, we only support single CU)
+	 * Also generate a relocation entry for this offset.
+	 */
+	RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc, 4,
+	    ds->ds_size, 0, cu->cu_abbrev_offset, ".debug_abbrev", error));
+
+	/* Pointer size. */
+	RCHECK(WRITE_VALUE(cu->cu_pointer_size, 1));
+
+	/* Transform the DIE(s) of this CU. */
+	RCHECK(_dwarf_die_gen(dbg, cu, drs, error));
+
+	/* Now we can fill in the length of this CU. */
+	cu->cu_length = ds->ds_size - 4;
+	offset = 0;
+	dbg->write(ds->ds_data, &offset, cu->cu_length, 4);
+
+	/* Inform application the creation of .debug_info ELF section. */
+	RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error));
+
+	/*
+	 * Inform application the creation of relocation section for
+	 * .debug_info.
+	 */
+	RCHECK(_dwarf_reloc_section_finalize(dbg, drs, error));
+
+	return (DW_DLE_NONE);
+
+gen_fail:
+	_dwarf_reloc_section_free(dbg, &drs);
+
+gen_fail0:
+	_dwarf_section_free(dbg, &dbg->dbgp_info);
+
+gen_fail1:
+	STAILQ_REMOVE(&dbg->dbg_cu, cu, _Dwarf_CU, cu_next);
+	free(cu);
+
+	return (ret);
+}
+
+void
+_dwarf_info_pro_cleanup(Dwarf_P_Debug dbg)
+{
+	Dwarf_CU cu;
+
+	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
+
+	cu = STAILQ_FIRST(&dbg->dbg_cu);
+	if (cu != NULL) {
+		STAILQ_REMOVE(&dbg->dbg_cu, cu, _Dwarf_CU, cu_next);
+		_dwarf_abbrev_cleanup(cu);
+		free(cu);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/libdwarf_init.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,315 @@
+/*-
+ * Copyright (c) 2009,2011 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: libdwarf_init.c 3136 2014-12-24 16:04:38Z kaiwang27 $");
+
+static int
+_dwarf_consumer_init(Dwarf_Debug dbg, Dwarf_Error *error)
+{
+	const Dwarf_Obj_Access_Methods *m;
+	Dwarf_Obj_Access_Section sec;
+	void *obj;
+	Dwarf_Unsigned cnt;
+	Dwarf_Half i;
+	int ret;
+
+	assert(dbg != NULL);
+	assert(dbg->dbg_iface != NULL);
+
+	m = dbg->dbg_iface->methods;
+	obj = dbg->dbg_iface->object;
+
+	assert(m != NULL);
+	assert(obj != NULL);
+
+	if (m->get_byte_order(obj) == DW_OBJECT_MSB) {
+		dbg->read = _dwarf_read_msb;
+		dbg->write = _dwarf_write_msb;
+		dbg->decode = _dwarf_decode_msb;
+	} else {
+		dbg->read = _dwarf_read_lsb;
+		dbg->write = _dwarf_write_lsb;
+		dbg->decode = _dwarf_decode_lsb;
+	}
+
+	dbg->dbg_pointer_size = m->get_pointer_size(obj);
+	dbg->dbg_offset_size = m->get_length_size(obj);
+
+	cnt = m->get_section_count(obj);
+
+	if (cnt == 0) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_INFO_NULL);
+		return (DW_DLE_DEBUG_INFO_NULL);
+	}
+
+	dbg->dbg_seccnt = cnt;
+
+	if ((dbg->dbg_section = calloc(cnt + 1, sizeof(Dwarf_Section))) ==
+	    NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+
+	for (i = 0; i < cnt; i++) {
+		if (m->get_section_info(obj, i, &sec, &ret) != DW_DLV_OK) {
+			DWARF_SET_ERROR(dbg, error, ret);
+			return (ret);
+		}
+
+		dbg->dbg_section[i].ds_addr = sec.addr;
+		dbg->dbg_section[i].ds_size = sec.size;
+		dbg->dbg_section[i].ds_name = sec.name;
+
+		if (m->load_section(obj, i, &dbg->dbg_section[i].ds_data, &ret)
+		    != DW_DLV_OK) {
+			DWARF_SET_ERROR(dbg, error, ret);
+			return (ret);
+		}
+	}
+	dbg->dbg_section[cnt].ds_name = NULL;
+
+	dbg->dbg_info_sec = _dwarf_find_section(dbg, ".debug_info");
+
+	/* Try to find the optional DWARF4 .debug_types section. */
+	dbg->dbg_types_sec = _dwarf_find_next_types_section(dbg, NULL);
+
+	/* Initialise call frame API related parameters. */
+	_dwarf_frame_params_init(dbg);
+
+	return (DW_DLV_OK);
+}
+
+static int
+_dwarf_producer_init(Dwarf_Debug dbg, Dwarf_Unsigned pf, Dwarf_Error *error)
+{
+
+	/* Producer only support DWARF2 which has fixed 32bit offset. */
+	dbg->dbg_offset_size = 4;
+
+	if (pf & DW_DLC_SIZE_32 && pf & DW_DLC_SIZE_64) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLE_ARGUMENT);
+	}
+
+	if ((pf & DW_DLC_SIZE_32) == 0 && (pf & DW_DLC_SIZE_64) == 0)
+		pf |= DW_DLC_SIZE_32;
+
+	if (pf & DW_DLC_SIZE_64)
+		dbg->dbg_pointer_size = 8;
+	else
+		dbg->dbg_pointer_size = 4;
+
+	if (pf & DW_DLC_ISA_IA64 && pf & DW_DLC_ISA_MIPS) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLE_ARGUMENT);
+	}
+
+	if (pf & DW_DLC_ISA_IA64)
+		dbg->dbgp_isa = DW_ISA_IA64;
+	else
+		dbg->dbgp_isa = DW_ISA_MIPS;
+
+	if (pf & DW_DLC_TARGET_BIGENDIAN && pf & DW_DLC_TARGET_LITTLEENDIAN) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLE_ARGUMENT);
+	}
+
+	if ((pf & DW_DLC_TARGET_BIGENDIAN) == 0 &&
+	    (pf & DW_DLC_TARGET_LITTLEENDIAN) == 0) {
+#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_BIG_ENDIAN
+		pf |= DW_DLC_TARGET_BIGENDIAN;
+#else
+		pf |= DW_DLC_TARGET_LITTLEENDIAN;
+#endif
+	}
+
+	if (pf & DW_DLC_TARGET_BIGENDIAN) {
+		dbg->write = _dwarf_write_msb;
+		dbg->write_alloc = _dwarf_write_msb_alloc;
+	} else if (pf & DW_DLC_TARGET_LITTLEENDIAN) {
+		dbg->write = _dwarf_write_lsb;
+		dbg->write_alloc = _dwarf_write_lsb_alloc;
+	} else
+		assert(0);
+
+	if (pf & DW_DLC_STREAM_RELOCATIONS &&
+	    pf & DW_DLC_SYMBOLIC_RELOCATIONS) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
+		return (DW_DLE_ARGUMENT);
+	}
+
+	if ((pf & DW_DLC_STREAM_RELOCATIONS) == 0 &&
+	    (pf & DW_DLC_SYMBOLIC_RELOCATIONS) == 0)
+		pf |= DW_DLC_STREAM_RELOCATIONS;
+
+	dbg->dbgp_flags = pf;
+
+	STAILQ_INIT(&dbg->dbgp_dielist);
+	STAILQ_INIT(&dbg->dbgp_pelist);
+	STAILQ_INIT(&dbg->dbgp_seclist);
+	STAILQ_INIT(&dbg->dbgp_drslist);
+	STAILQ_INIT(&dbg->dbgp_cielist);
+	STAILQ_INIT(&dbg->dbgp_fdelist);
+
+	if ((dbg->dbgp_lineinfo = calloc(1, sizeof(struct _Dwarf_LineInfo))) ==
+	    NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+	STAILQ_INIT(&dbg->dbgp_lineinfo->li_lflist);
+	STAILQ_INIT(&dbg->dbgp_lineinfo->li_lnlist);
+
+	if ((dbg->dbgp_as = calloc(1, sizeof(struct _Dwarf_ArangeSet))) ==
+	    NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+	STAILQ_INIT(&dbg->dbgp_as->as_arlist);
+
+	return (DW_DLE_NONE);
+}
+
+int
+_dwarf_init(Dwarf_Debug dbg, Dwarf_Unsigned pro_flags, Dwarf_Handler errhand,
+    Dwarf_Ptr errarg, Dwarf_Error *error)
+{
+	int ret;
+
+	ret = DW_DLE_NONE;
+	
+	/*
+	 * Set the error handler fields early, so that the application
+	 * is notified of initialization errors.
+	 */
+	dbg->dbg_errhand = errhand;
+	dbg->dbg_errarg = errarg;
+
+	STAILQ_INIT(&dbg->dbg_cu);
+	STAILQ_INIT(&dbg->dbg_tu);
+	STAILQ_INIT(&dbg->dbg_rllist);
+	STAILQ_INIT(&dbg->dbg_aslist);
+	STAILQ_INIT(&dbg->dbg_mslist);
+
+	if (dbg->dbg_mode == DW_DLC_READ || dbg->dbg_mode == DW_DLC_RDWR) {
+		ret = _dwarf_consumer_init(dbg, error);
+		if (ret != DW_DLE_NONE) {
+			_dwarf_deinit(dbg);
+			return (ret);
+		}
+	}
+
+	if (dbg->dbg_mode == DW_DLC_WRITE) {
+		ret = _dwarf_producer_init(dbg, pro_flags, error);
+		if (ret != DW_DLE_NONE) {
+			_dwarf_deinit(dbg);
+			return (ret);
+		}
+	}
+
+	/*
+	 * Initialise internal string table.
+	 */
+	if ((ret = _dwarf_strtab_init(dbg, error)) != DW_DLE_NONE)
+		return (ret);
+
+	return (DW_DLE_NONE);
+}
+
+static void
+_dwarf_producer_deinit(Dwarf_P_Debug dbg)
+{
+
+	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
+
+	_dwarf_info_pro_cleanup(dbg);
+	_dwarf_die_pro_cleanup(dbg);
+	_dwarf_expr_cleanup(dbg);
+	_dwarf_lineno_pro_cleanup(dbg);
+	_dwarf_frame_pro_cleanup(dbg);
+	_dwarf_arange_pro_cleanup(dbg);
+	_dwarf_macinfo_pro_cleanup(dbg);
+	_dwarf_strtab_cleanup(dbg);
+	_dwarf_nametbl_pro_cleanup(&dbg->dbgp_pubs);
+	_dwarf_nametbl_pro_cleanup(&dbg->dbgp_weaks);
+	_dwarf_nametbl_pro_cleanup(&dbg->dbgp_funcs);
+	_dwarf_nametbl_pro_cleanup(&dbg->dbgp_types);
+	_dwarf_nametbl_pro_cleanup(&dbg->dbgp_vars);
+	_dwarf_section_cleanup(dbg);
+	_dwarf_reloc_cleanup(dbg);
+}
+
+static void
+_dwarf_consumer_deinit(Dwarf_Debug dbg)
+{
+
+	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_READ);
+
+	_dwarf_info_cleanup(dbg);
+	_dwarf_ranges_cleanup(dbg);
+	_dwarf_frame_cleanup(dbg);
+	_dwarf_arange_cleanup(dbg);
+	_dwarf_macinfo_cleanup(dbg);
+	_dwarf_strtab_cleanup(dbg);
+	_dwarf_nametbl_cleanup(&dbg->dbg_globals);
+	_dwarf_nametbl_cleanup(&dbg->dbg_pubtypes);
+	_dwarf_nametbl_cleanup(&dbg->dbg_weaks);
+	_dwarf_nametbl_cleanup(&dbg->dbg_funcs);
+	_dwarf_nametbl_cleanup(&dbg->dbg_vars);
+	_dwarf_nametbl_cleanup(&dbg->dbg_types);
+
+	free(dbg->dbg_section);
+}
+
+void
+_dwarf_deinit(Dwarf_Debug dbg)
+{
+
+	assert(dbg != NULL);
+
+	if (dbg->dbg_mode == DW_DLC_READ)
+		_dwarf_consumer_deinit(dbg);
+	else if (dbg->dbg_mode == DW_DLC_WRITE)
+		_dwarf_producer_deinit(dbg);
+}
+
+int
+_dwarf_alloc(Dwarf_Debug *ret_dbg, int mode, Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+
+	if ((dbg = calloc(sizeof(struct _Dwarf_Debug), 1)) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+
+	dbg->dbg_mode = mode;
+
+	*ret_dbg = dbg;
+
+	return (DW_DLE_NONE);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/libdwarf_lineno.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,777 @@
+/*-
+ * Copyright (c) 2009,2010 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: libdwarf_lineno.c 3164 2015-02-19 01:20:12Z kaiwang27 $");
+
+static int
+_dwarf_lineno_add_file(Dwarf_LineInfo li, uint8_t **p, const char *compdir,
+    Dwarf_Error *error, Dwarf_Debug dbg)
+{
+	Dwarf_LineFile lf;
+	const char *dirname;
+	uint8_t *src;
+	int slen;
+
+	src = *p;
+
+	if ((lf = malloc(sizeof(struct _Dwarf_LineFile))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+
+	lf->lf_fullpath = NULL;
+	lf->lf_fname = (char *) src;
+	src += strlen(lf->lf_fname) + 1;
+	lf->lf_dirndx = _dwarf_decode_uleb128(&src);
+	if (lf->lf_dirndx > li->li_inclen) {
+		free(lf);
+		DWARF_SET_ERROR(dbg, error, DW_DLE_DIR_INDEX_BAD);
+		return (DW_DLE_DIR_INDEX_BAD);
+	}
+
+	/* Make full pathname if need. */
+	if (*lf->lf_fname != '/') {
+		dirname = compdir;
+		if (lf->lf_dirndx > 0)
+			dirname = li->li_incdirs[lf->lf_dirndx - 1];
+		if (dirname != NULL) {
+			slen = strlen(dirname) + strlen(lf->lf_fname) + 2;
+			if ((lf->lf_fullpath = malloc(slen)) == NULL) {
+				free(lf);
+				DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+				return (DW_DLE_MEMORY);
+			}
+			snprintf(lf->lf_fullpath, slen, "%s/%s", dirname,
+			    lf->lf_fname);
+		}
+	}
+
+	lf->lf_mtime = _dwarf_decode_uleb128(&src);
+	lf->lf_size = _dwarf_decode_uleb128(&src);
+	STAILQ_INSERT_TAIL(&li->li_lflist, lf, lf_next);
+	li->li_lflen++;
+
+	*p = src;
+
+	return (DW_DLE_NONE);
+}
+
+static int
+_dwarf_lineno_run_program(Dwarf_CU cu, Dwarf_LineInfo li, uint8_t *p,
+    uint8_t *pe, const char *compdir, Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+	Dwarf_Line ln, tln;
+	uint64_t address, file, line, column, opsize;
+	int is_stmt, basic_block, end_sequence;
+	int ret;
+
+#define	RESET_REGISTERS						\
+	do {							\
+		address	       = 0;				\
+		file	       = 1;				\
+		line	       = 1;				\
+		column	       = 0;				\
+		is_stmt	       = li->li_defstmt;		\
+		basic_block    = 0;				\
+		end_sequence   = 0;				\
+	} while(0)
+
+#define	APPEND_ROW						\
+	do {							\
+		ln = malloc(sizeof(struct _Dwarf_Line));	\
+		if (ln == NULL) {				\
+			ret = DW_DLE_MEMORY;			\
+			DWARF_SET_ERROR(dbg, error, ret);	\
+			goto prog_fail;				\
+		}						\
+		ln->ln_li     = li;				\
+		ln->ln_addr   = address;			\
+		ln->ln_symndx = 0;				\
+		ln->ln_fileno = file;				\
+		ln->ln_lineno = line;				\
+		ln->ln_column = column;				\
+		ln->ln_bblock = basic_block;			\
+		ln->ln_stmt   = is_stmt;			\
+		ln->ln_endseq = end_sequence;			\
+		STAILQ_INSERT_TAIL(&li->li_lnlist, ln, ln_next);\
+		li->li_lnlen++;					\
+	} while(0)
+
+#define	LINE(x) (li->li_lbase + (((x) - li->li_opbase) % li->li_lrange))
+#define	ADDRESS(x) ((((x) - li->li_opbase) / li->li_lrange) * li->li_minlen)
+
+	dbg = cu->cu_dbg;
+
+	/*
+	 * Set registers to their default values.
+	 */
+	RESET_REGISTERS;
+
+	/*
+	 * Start line number program.
+	 */
+	while (p < pe) {
+		if (*p == 0) {
+
+			/*
+			 * Extended Opcodes.
+			 */
+
+			p++;
+			opsize = _dwarf_decode_uleb128(&p);
+			switch (*p) {
+			case DW_LNE_end_sequence:
+				p++;
+				end_sequence = 1;
+				APPEND_ROW;
+				RESET_REGISTERS;
+				break;
+			case DW_LNE_set_address:
+				p++;
+				address = dbg->decode(&p, cu->cu_pointer_size);
+				break;
+			case DW_LNE_define_file:
+				p++;
+				ret = _dwarf_lineno_add_file(li, &p, compdir,
+				    error, dbg);
+				if (ret != DW_DLE_NONE)
+					goto prog_fail;
+				break;
+			default:
+				/* Unrecognized extened opcodes. */
+				p += opsize;
+			}
+
+		} else if (*p > 0 && *p < li->li_opbase) {
+
+			/*
+			 * Standard Opcodes.
+			 */
+
+			switch (*p++) {
+			case DW_LNS_copy:
+				APPEND_ROW;
+				basic_block = 0;
+				break;
+			case DW_LNS_advance_pc:
+				address += _dwarf_decode_uleb128(&p) *
+				    li->li_minlen;
+				break;
+			case DW_LNS_advance_line:
+				line += _dwarf_decode_sleb128(&p);
+				break;
+			case DW_LNS_set_file:
+				file = _dwarf_decode_uleb128(&p);
+				break;
+			case DW_LNS_set_column:
+				column = _dwarf_decode_uleb128(&p);
+				break;
+			case DW_LNS_negate_stmt:
+				is_stmt = !is_stmt;
+				break;
+			case DW_LNS_set_basic_block:
+				basic_block = 1;
+				break;
+			case DW_LNS_const_add_pc:
+				address += ADDRESS(255);
+				break;
+			case DW_LNS_fixed_advance_pc:
+				address += dbg->decode(&p, 2);
+				break;
+			case DW_LNS_set_prologue_end:
+				break;
+			case DW_LNS_set_epilogue_begin:
+				break;
+			case DW_LNS_set_isa:
+				(void) _dwarf_decode_uleb128(&p);
+				break;
+			default:
+				/* Unrecognized extened opcodes. What to do? */
+				break;
+			}
+
+		} else {
+
+			/*
+			 * Special Opcodes.
+			 */
+
+			line += LINE(*p);
+			address += ADDRESS(*p);
+			APPEND_ROW;
+			basic_block = 0;
+			p++;
+		}
+	}
+
+	return (DW_DLE_NONE);
+
+prog_fail:
+
+	STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) {
+		STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line, ln_next);
+		free(ln);
+	}
+
+	return (ret);
+
+#undef	RESET_REGISTERS
+#undef	APPEND_ROW
+#undef	LINE
+#undef	ADDRESS
+}
+
+int
+_dwarf_lineno_init(Dwarf_Die die, uint64_t offset, Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+	Dwarf_Section *ds;
+	Dwarf_CU cu;
+	Dwarf_Attribute at;
+	Dwarf_LineInfo li;
+	Dwarf_LineFile lf, tlf;
+	const char *compdir;
+	uint64_t length, hdroff, endoff;
+	uint8_t *p;
+	int dwarf_size, i, ret;
+
+	cu = die->die_cu;
+	assert(cu != NULL);
+
+	dbg = cu->cu_dbg;
+	assert(dbg != NULL);
+
+	if ((ds = _dwarf_find_section(dbg, ".debug_line")) == NULL)
+		return (DW_DLE_NONE);
+
+	/*
+	 * Try to find out the dir where the CU was compiled. Later we
+	 * will use the dir to create full pathnames, if need.
+	 */
+	compdir = NULL;
+	at = _dwarf_attr_find(die, DW_AT_comp_dir);
+	if (at != NULL) {
+		switch (at->at_form) {
+		case DW_FORM_strp:
+			compdir = at->u[1].s;
+			break;
+		case DW_FORM_string:
+			compdir = at->u[0].s;
+			break;
+		default:
+			break;
+		}
+	}
+
+	length = dbg->read(ds->ds_data, &offset, 4);
+	if (length == 0xffffffff) {
+		dwarf_size = 8;
+		length = dbg->read(ds->ds_data, &offset, 8);
+	} else
+		dwarf_size = 4;
+
+	if (length > ds->ds_size - offset) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_LINE_LENGTH_BAD);
+		return (DW_DLE_DEBUG_LINE_LENGTH_BAD);
+	}
+
+	if ((li = calloc(1, sizeof(struct _Dwarf_LineInfo))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+
+	/*
+	 * Read in line number program header.
+	 */
+	li->li_length = length;
+	endoff = offset + length;
+	li->li_version = dbg->read(ds->ds_data, &offset, 2); /* FIXME: verify version */
+	li->li_hdrlen = dbg->read(ds->ds_data, &offset, dwarf_size);
+	hdroff = offset;
+	li->li_minlen = dbg->read(ds->ds_data, &offset, 1);
+	if (li->li_version == 4)
+		li->li_maxop = dbg->read(ds->ds_data, &offset, 1);
+	li->li_defstmt = dbg->read(ds->ds_data, &offset, 1);
+	li->li_lbase = dbg->read(ds->ds_data, &offset, 1);
+	li->li_lrange = dbg->read(ds->ds_data, &offset, 1);
+	li->li_opbase = dbg->read(ds->ds_data, &offset, 1);
+	STAILQ_INIT(&li->li_lflist);
+	STAILQ_INIT(&li->li_lnlist);
+
+	if ((int)li->li_hdrlen - 5 < li->li_opbase - 1) {
+		ret = DW_DLE_DEBUG_LINE_LENGTH_BAD;
+		DWARF_SET_ERROR(dbg, error, ret);
+		goto fail_cleanup;
+	}
+
+	if ((li->li_oplen = malloc(li->li_opbase)) == NULL) {
+		ret = DW_DLE_MEMORY;
+		DWARF_SET_ERROR(dbg, error, ret);
+		goto fail_cleanup;
+	}
+
+	/*
+	 * Read in std opcode arg length list. Note that the first
+	 * element is not used.
+	 */
+	for (i = 1; i < li->li_opbase; i++)
+		li->li_oplen[i] = dbg->read(ds->ds_data, &offset, 1);
+
+	/*
+	 * Check how many strings in the include dir string array.
+	 */
+	length = 0;
+	p = ds->ds_data + offset;
+	while (*p != '\0') {
+		while (*p++ != '\0')
+			;
+		length++;
+	}
+	li->li_inclen = length;
+
+	/* Sanity check. */
+	if (p - ds->ds_data > (int) ds->ds_size) {
+		ret = DW_DLE_DEBUG_LINE_LENGTH_BAD;
+		DWARF_SET_ERROR(dbg, error, ret);
+		goto fail_cleanup;
+	}
+
+	if (length != 0) {
+		if ((li->li_incdirs = malloc(length * sizeof(char *))) ==
+		    NULL) {
+			ret = DW_DLE_MEMORY;
+			DWARF_SET_ERROR(dbg, error, ret);
+			goto fail_cleanup;
+		}
+	}
+
+	/* Fill in include dir array. */
+	i = 0;
+	p = ds->ds_data + offset;
+	while (*p != '\0') {
+		li->li_incdirs[i++] = (char *) p;
+		while (*p++ != '\0')
+			;
+	}
+
+	p++;
+
+	/*
+	 * Process file list.
+	 */
+	while (*p != '\0') {
+		ret = _dwarf_lineno_add_file(li, &p, compdir, error, dbg);
+		if (ret != DW_DLE_NONE)
+			goto fail_cleanup;
+		if (p - ds->ds_data > (int) ds->ds_size) {
+			ret = DW_DLE_DEBUG_LINE_LENGTH_BAD;
+			DWARF_SET_ERROR(dbg, error, ret);
+			goto fail_cleanup;
+		}
+	}
+
+	p++;
+
+	/* Sanity check. */
+	if (p - ds->ds_data - hdroff != li->li_hdrlen) {
+		ret = DW_DLE_DEBUG_LINE_LENGTH_BAD;
+		DWARF_SET_ERROR(dbg, error, ret);
+		goto fail_cleanup;
+	}
+
+	/*
+	 * Process line number program.
+	 */
+	ret = _dwarf_lineno_run_program(cu, li, p, ds->ds_data + endoff, compdir,
+	    error);
+	if (ret != DW_DLE_NONE)
+		goto fail_cleanup;
+
+	cu->cu_lineinfo = li;
+
+	return (DW_DLE_NONE);
+
+fail_cleanup:
+
+	STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) {
+		STAILQ_REMOVE(&li->li_lflist, lf, _Dwarf_LineFile, lf_next);
+		if (lf->lf_fullpath)
+			free(lf->lf_fullpath);
+		free(lf);
+	}
+
+	if (li->li_oplen)
+		free(li->li_oplen);
+	if (li->li_incdirs)
+		free(li->li_incdirs);
+	free(li);
+
+	return (ret);
+}
+
+void
+_dwarf_lineno_cleanup(Dwarf_LineInfo li)
+{
+	Dwarf_LineFile lf, tlf;
+	Dwarf_Line ln, tln;
+
+	if (li == NULL)
+		return;
+	STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) {
+		STAILQ_REMOVE(&li->li_lflist, lf,
+		    _Dwarf_LineFile, lf_next);
+		if (lf->lf_fullpath)
+			free(lf->lf_fullpath);
+		free(lf);
+	}
+	STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) {
+		STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line,
+		    ln_next);
+		free(ln);
+	}
+	if (li->li_oplen)
+		free(li->li_oplen);
+	if (li->li_incdirs)
+		free(li->li_incdirs);
+	if (li->li_lnarray)
+		free(li->li_lnarray);
+	if (li->li_lfnarray)
+		free(li->li_lfnarray);
+	free(li);
+}
+
+static int
+_dwarf_lineno_gen_program(Dwarf_P_Debug dbg, Dwarf_P_Section ds,
+    Dwarf_Rel_Section drs, Dwarf_Error * error)
+{
+	Dwarf_LineInfo li;
+	Dwarf_Line ln;
+	Dwarf_Unsigned address, file, line, spc;
+	Dwarf_Unsigned addr0, maddr;
+	Dwarf_Signed line0, column;
+	int is_stmt, basic_block;
+	int need_copy;
+	int ret;
+
+#define	RESET_REGISTERS						\
+	do {							\
+		address	       = 0;				\
+		file	       = 1;				\
+		line	       = 1;				\
+		column	       = 0;				\
+		is_stmt	       = li->li_defstmt;		\
+		basic_block    = 0;				\
+	} while(0)
+
+	li = dbg->dbgp_lineinfo;
+	maddr = (255 - li->li_opbase) / li->li_lrange;
+
+	RESET_REGISTERS;
+
+	STAILQ_FOREACH(ln, &li->li_lnlist, ln_next) {
+		if (ln->ln_symndx > 0) {
+			/*
+			 * Generate DW_LNE_set_address extended op.
+			 */
+			RCHECK(WRITE_VALUE(0, 1));
+			RCHECK(WRITE_ULEB128(dbg->dbg_pointer_size + 1));
+			RCHECK(WRITE_VALUE(DW_LNE_set_address, 1));
+			RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds,
+			    dwarf_drt_data_reloc, dbg->dbg_pointer_size,
+			    ds->ds_size, ln->ln_symndx, ln->ln_addr,
+			    NULL, error));
+			address = ln->ln_addr;
+			continue;
+		} else if (ln->ln_endseq) {
+			addr0 = (ln->ln_addr - address) / li->li_minlen;
+			if (addr0 != 0) {
+				RCHECK(WRITE_VALUE(DW_LNS_advance_pc, 1));
+				RCHECK(WRITE_ULEB128(addr0));
+			}
+
+			/*
+			 * Generate DW_LNE_end_sequence.
+			 */
+			RCHECK(WRITE_VALUE(0, 1));
+			RCHECK(WRITE_ULEB128(1));
+			RCHECK(WRITE_VALUE(DW_LNE_end_sequence, 1));
+			RESET_REGISTERS;
+			continue;
+		}
+
+		/*
+		 * Generate standard opcodes for file, column, is_stmt or
+		 * basic_block changes.
+		 */
+		if (ln->ln_fileno != file) {
+			RCHECK(WRITE_VALUE(DW_LNS_set_file, 1));
+			RCHECK(WRITE_ULEB128(ln->ln_fileno));
+			file = ln->ln_fileno;
+		}
+		if (ln->ln_column != column) {
+			RCHECK(WRITE_VALUE(DW_LNS_set_column, 1));
+			RCHECK(WRITE_ULEB128(ln->ln_column));
+			column = ln->ln_column;
+		}
+		if (ln->ln_stmt != is_stmt) {
+			RCHECK(WRITE_VALUE(DW_LNS_negate_stmt, 1));
+			is_stmt = ln->ln_stmt;
+		}
+		if (ln->ln_bblock && !basic_block) {
+			RCHECK(WRITE_VALUE(DW_LNS_set_basic_block, 1));
+			basic_block = 1;
+		}
+
+		/*
+		 * Calculate address and line number change.
+		 */
+		addr0 = (ln->ln_addr - address) / li->li_minlen;
+		line0 = ln->ln_lineno - line;
+
+		if (addr0 == 0 && line0 == 0)
+			continue;
+
+		/*
+		 * Check if line delta is with the range and if the special
+		 * opcode can be used.
+		 */
+		assert(li->li_lbase <= 0);
+		if (line0 >= li->li_lbase &&
+		    line0 <= li->li_lbase + li->li_lrange - 1) {
+			spc = (line0 - li->li_lbase) +
+			    (li->li_lrange * addr0) + li->li_opbase;
+			if (spc <= 255) {
+				RCHECK(WRITE_VALUE(spc, 1));
+				basic_block = 0;
+				goto next_line;
+			}
+		}
+
+		/* Generate DW_LNS_advance_line for line number change. */
+		if (line0 != 0) {
+			RCHECK(WRITE_VALUE(DW_LNS_advance_line, 1));
+			RCHECK(WRITE_SLEB128(line0));
+			line0 = 0;
+			need_copy = 1;
+		} else
+			need_copy = basic_block;
+
+		if (addr0 != 0) {
+			/* See if it can be handled by DW_LNS_const_add_pc. */
+			spc = (line0 - li->li_lbase) +
+			    (li->li_lrange * (addr0 - maddr)) + li->li_opbase;
+			if (addr0 >= maddr && spc <= 255) {
+				RCHECK(WRITE_VALUE(DW_LNS_const_add_pc, 1));
+				RCHECK(WRITE_VALUE(spc, 1));
+			} else {
+				/* Otherwise we use DW_LNS_advance_pc. */
+				RCHECK(WRITE_VALUE(DW_LNS_advance_pc, 1));
+				RCHECK(WRITE_ULEB128(addr0));
+			}
+		}
+
+		if (need_copy) {
+			RCHECK(WRITE_VALUE(DW_LNS_copy, 1));
+			basic_block = 0;
+		}
+
+	next_line:
+		address = ln->ln_addr;
+		line = ln->ln_lineno;
+	}
+
+	return (DW_DLE_NONE);
+
+gen_fail:
+	return (ret);
+
+#undef	RESET_REGISTERS
+}
+
+static uint8_t
+_dwarf_get_minlen(Dwarf_P_Debug dbg)
+{
+
+	assert(dbg != NULL);
+
+	switch (dbg->dbgp_isa) {
+	case DW_ISA_ARM:
+		return (2);
+	case DW_ISA_X86:
+	case DW_ISA_X86_64:
+		return (1);
+	default:
+		return (4);
+	}
+}
+
+static uint8_t oplen[] = {0, 1, 1, 1, 1, 0, 0, 0, 1};
+
+int
+_dwarf_lineno_gen(Dwarf_P_Debug dbg, Dwarf_Error *error)
+{
+	Dwarf_LineInfo li;
+	Dwarf_LineFile lf;
+	Dwarf_P_Section ds;
+	Dwarf_Rel_Section drs;
+	Dwarf_Unsigned offset;
+	int i, ret;
+
+	assert(dbg != NULL && dbg->dbgp_lineinfo != NULL);
+
+	li = dbg->dbgp_lineinfo;
+	if (STAILQ_EMPTY(&li->li_lnlist))
+		return (DW_DLE_NONE);
+
+	li->li_length = 0;
+	li->li_version = 2;
+	li->li_hdrlen = 0;
+	li->li_minlen = _dwarf_get_minlen(dbg);
+	li->li_defstmt = 1;
+	li->li_lbase = -5;
+	li->li_lrange = 14;
+	li->li_opbase = 10;
+
+	/* Create .debug_line section. */
+	if ((ret = _dwarf_section_init(dbg, &ds, ".debug_line", 0, error)) !=
+	    DW_DLE_NONE)
+		return (ret);
+
+	/* Create relocation section for .debug_line */
+	if ((ret = _dwarf_reloc_section_init(dbg, &drs, ds, error)) !=
+	    DW_DLE_NONE)
+		goto gen_fail1;
+
+	/* Length placeholder. (We only use 32-bit DWARF format) */
+	RCHECK(WRITE_VALUE(0, 4));
+
+	/* Write line number dwarf version. (DWARF2) */
+	RCHECK(WRITE_VALUE(li->li_version, 2));
+
+	/* Header length placeholder. */
+	offset = ds->ds_size;
+	RCHECK(WRITE_VALUE(li->li_hdrlen, 4));
+
+	/* Write minimum instruction length. */
+	RCHECK(WRITE_VALUE(li->li_minlen, 1));
+
+	/*
+	 * Write initial value for is_stmt. XXX Which default value we
+	 * should use?
+	 */
+	RCHECK(WRITE_VALUE(li->li_defstmt, 1));
+
+	/*
+	 * Write line_base and line_range. FIXME These value needs to be
+	 * fine tuned.
+	 */
+	RCHECK(WRITE_VALUE(li->li_lbase, 1));
+	RCHECK(WRITE_VALUE(li->li_lrange, 1));
+
+	/* Write opcode_base. (DWARF2) */
+	RCHECK(WRITE_VALUE(li->li_opbase, 1));
+
+	/* Write standard op length array. */
+	RCHECK(WRITE_BLOCK(oplen, sizeof(oplen) / sizeof(oplen[0])));
+
+	/* Write the list of include directories. */
+	for (i = 0; (Dwarf_Unsigned) i < li->li_inclen; i++)
+		RCHECK(WRITE_STRING(li->li_incdirs[i]));
+	RCHECK(WRITE_VALUE(0, 1));
+
+	/* Write the list of filenames. */
+	STAILQ_FOREACH(lf, &li->li_lflist, lf_next) {
+		RCHECK(WRITE_STRING(lf->lf_fname));
+		RCHECK(WRITE_ULEB128(lf->lf_dirndx));
+		RCHECK(WRITE_ULEB128(lf->lf_mtime));
+		RCHECK(WRITE_ULEB128(lf->lf_size));
+	}
+	RCHECK(WRITE_VALUE(0, 1));
+
+	/* Fill in the header length. */
+	li->li_hdrlen = ds->ds_size - offset - 4;
+	dbg->write(ds->ds_data, &offset, li->li_hdrlen, 4);
+
+	/* Generate the line number program. */
+	RCHECK(_dwarf_lineno_gen_program(dbg, ds, drs, error));
+
+	/* Fill in the length of this line info. */
+	li->li_length = ds->ds_size - 4;
+	offset = 0;
+	dbg->write(ds->ds_data, &offset, li->li_length, 4);
+
+	/* Notify the creation of .debug_line ELF section. */
+	RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error));
+
+	/* Finalize relocation section for .debug_line. */
+	RCHECK(_dwarf_reloc_section_finalize(dbg, drs, error));
+
+	return (DW_DLE_NONE);
+
+gen_fail:
+	_dwarf_reloc_section_free(dbg, &drs);
+
+gen_fail1:
+	_dwarf_section_free(dbg, &ds);
+
+	return (ret);
+}
+
+void
+_dwarf_lineno_pro_cleanup(Dwarf_P_Debug dbg)
+{
+	Dwarf_LineInfo li;
+	Dwarf_LineFile lf, tlf;
+	Dwarf_Line ln, tln;
+	int i;
+
+	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
+	if (dbg->dbgp_lineinfo == NULL)
+		return;
+
+	li = dbg->dbgp_lineinfo;
+	STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) {
+		STAILQ_REMOVE(&li->li_lflist, lf, _Dwarf_LineFile,
+		    lf_next);
+		if (lf->lf_fname)
+			free(lf->lf_fname);
+		free(lf);
+	}
+	STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) {
+		STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line, ln_next);
+		free(ln);
+	}
+	if (li->li_incdirs) {
+		for (i = 0; (Dwarf_Unsigned) i < li->li_inclen; i++)
+			free(li->li_incdirs[i]);
+		free(li->li_incdirs);
+	}
+	free(li);
+	dbg->dbgp_lineinfo = NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/libdwarf_loc.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,701 @@
+/*-
+ * Copyright (c) 2007 John Birrell (jb@freebsd.org)
+ * Copyright (c) 2014 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: libdwarf_loc.c 3070 2014-06-23 03:08:33Z kaiwang27 $");
+
+/*
+ * Given an array of bytes of length 'len' representing a
+ * DWARF expression, compute the number of operations based
+ * on there being one byte describing the operation and
+ * zero or more bytes of operands as defined in the standard
+ * for each operation type. Also, if lbuf is non-null, store
+ * the opcode and oprand in it.
+ */
+static int
+_dwarf_loc_fill_loc(Dwarf_Debug dbg, Dwarf_Locdesc *lbuf, uint8_t pointer_size,
+    uint8_t offset_size, uint8_t version, uint8_t *p, int len)
+{
+	int count;
+	uint64_t operand1;
+	uint64_t operand2;
+	uint8_t *ps, *pe, s;
+
+	count = 0;
+	ps = p;
+	pe = p + len;
+
+	/*
+	 * Process each byte. If an error occurs, then the
+	 * count will be set to -1.
+	 */
+	while (p < pe) {
+
+		operand1 = 0;
+		operand2 = 0;
+
+		if (lbuf != NULL) {
+			lbuf->ld_s[count].lr_atom = *p;
+			lbuf->ld_s[count].lr_offset = p - ps;
+		}
+
+		switch (*p++) {
+		/* Operations with no operands. */
+		case DW_OP_deref:
+		case DW_OP_reg0:
+		case DW_OP_reg1:
+		case DW_OP_reg2:
+		case DW_OP_reg3:
+		case DW_OP_reg4:
+		case DW_OP_reg5:
+		case DW_OP_reg6:
+		case DW_OP_reg7:
+		case DW_OP_reg8:
+		case DW_OP_reg9:
+		case DW_OP_reg10:
+		case DW_OP_reg11:
+		case DW_OP_reg12:
+		case DW_OP_reg13:
+		case DW_OP_reg14:
+		case DW_OP_reg15:
+		case DW_OP_reg16:
+		case DW_OP_reg17:
+		case DW_OP_reg18:
+		case DW_OP_reg19:
+		case DW_OP_reg20:
+		case DW_OP_reg21:
+		case DW_OP_reg22:
+		case DW_OP_reg23:
+		case DW_OP_reg24:
+		case DW_OP_reg25:
+		case DW_OP_reg26:
+		case DW_OP_reg27:
+		case DW_OP_reg28:
+		case DW_OP_reg29:
+		case DW_OP_reg30:
+		case DW_OP_reg31:
+
+		case DW_OP_lit0:
+		case DW_OP_lit1:
+		case DW_OP_lit2:
+		case DW_OP_lit3:
+		case DW_OP_lit4:
+		case DW_OP_lit5:
+		case DW_OP_lit6:
+		case DW_OP_lit7:
+		case DW_OP_lit8:
+		case DW_OP_lit9:
+		case DW_OP_lit10:
+		case DW_OP_lit11:
+		case DW_OP_lit12:
+		case DW_OP_lit13:
+		case DW_OP_lit14:
+		case DW_OP_lit15:
+		case DW_OP_lit16:
+		case DW_OP_lit17:
+		case DW_OP_lit18:
+		case DW_OP_lit19:
+		case DW_OP_lit20:
+		case DW_OP_lit21:
+		case DW_OP_lit22:
+		case DW_OP_lit23:
+		case DW_OP_lit24:
+		case DW_OP_lit25:
+		case DW_OP_lit26:
+		case DW_OP_lit27:
+		case DW_OP_lit28:
+		case DW_OP_lit29:
+		case DW_OP_lit30:
+		case DW_OP_lit31:
+
+		case DW_OP_dup:
+		case DW_OP_drop:
+
+		case DW_OP_over:
+
+		case DW_OP_swap:
+		case DW_OP_rot:
+		case DW_OP_xderef:
+
+		case DW_OP_abs:
+		case DW_OP_and:
+		case DW_OP_div:
+		case DW_OP_minus:
+		case DW_OP_mod:
+		case DW_OP_mul:
+		case DW_OP_neg:
+		case DW_OP_not:
+		case DW_OP_or:
+		case DW_OP_plus:
+
+		case DW_OP_shl:
+		case DW_OP_shr:
+		case DW_OP_shra:
+		case DW_OP_xor:
+
+		case DW_OP_eq:
+		case DW_OP_ge:
+		case DW_OP_gt:
+		case DW_OP_le:
+		case DW_OP_lt:
+		case DW_OP_ne:
+
+		case DW_OP_nop:
+		case DW_OP_push_object_address:
+		case DW_OP_form_tls_address:
+		case DW_OP_call_frame_cfa:
+		case DW_OP_stack_value:
+		case DW_OP_GNU_push_tls_address:
+		case DW_OP_GNU_uninit:
+			break;
+
+		/* Operations with 1-byte operands. */
+		case DW_OP_const1u:
+		case DW_OP_pick:
+		case DW_OP_deref_size:
+		case DW_OP_xderef_size:
+			operand1 = *p++;
+			break;
+
+		case DW_OP_const1s:
+			operand1 = (int8_t) *p++;
+			break;
+
+		/* Operations with 2-byte operands. */
+		case DW_OP_call2:
+		case DW_OP_const2u:
+		case DW_OP_bra:
+		case DW_OP_skip:
+			operand1 = dbg->decode(&p, 2);
+			break;
+
+		case DW_OP_const2s:
+			operand1 = (int16_t) dbg->decode(&p, 2);
+			break;
+
+		/* Operations with 4-byte operands. */
+		case DW_OP_call4:
+		case DW_OP_const4u:
+		case DW_OP_GNU_parameter_ref:
+			operand1 = dbg->decode(&p, 4);
+			break;
+
+		case DW_OP_const4s:
+			operand1 = (int32_t) dbg->decode(&p, 4);
+			break;
+
+		/* Operations with 8-byte operands. */
+		case DW_OP_const8u:
+		case DW_OP_const8s:
+			operand1 = dbg->decode(&p, 8);
+			break;
+
+		/* Operations with an unsigned LEB128 operand. */
+		case DW_OP_constu:
+		case DW_OP_plus_uconst:
+		case DW_OP_regx:
+		case DW_OP_piece:
+		case DW_OP_GNU_deref_type:
+		case DW_OP_GNU_convert:
+		case DW_OP_GNU_reinterpret:
+			operand1 = _dwarf_decode_uleb128(&p);
+			break;
+
+		/* Operations with a signed LEB128 operand. */
+		case DW_OP_consts:
+		case DW_OP_breg0:
+		case DW_OP_breg1:
+		case DW_OP_breg2:
+		case DW_OP_breg3:
+		case DW_OP_breg4:
+		case DW_OP_breg5:
+		case DW_OP_breg6:
+		case DW_OP_breg7:
+		case DW_OP_breg8:
+		case DW_OP_breg9:
+		case DW_OP_breg10:
+		case DW_OP_breg11:
+		case DW_OP_breg12:
+		case DW_OP_breg13:
+		case DW_OP_breg14:
+		case DW_OP_breg15:
+		case DW_OP_breg16:
+		case DW_OP_breg17:
+		case DW_OP_breg18:
+		case DW_OP_breg19:
+		case DW_OP_breg20:
+		case DW_OP_breg21:
+		case DW_OP_breg22:
+		case DW_OP_breg23:
+		case DW_OP_breg24:
+		case DW_OP_breg25:
+		case DW_OP_breg26:
+		case DW_OP_breg27:
+		case DW_OP_breg28:
+		case DW_OP_breg29:
+		case DW_OP_breg30:
+		case DW_OP_breg31:
+		case DW_OP_fbreg:
+			operand1 = _dwarf_decode_sleb128(&p);
+			break;
+
+		/*
+		 * Oeration with two unsigned LEB128 operands.
+		 */
+		case DW_OP_bit_piece:
+		case DW_OP_GNU_regval_type:
+			operand1 = _dwarf_decode_uleb128(&p);
+			operand2 = _dwarf_decode_uleb128(&p);
+			break;
+
+		/*
+		 * Operations with an unsigned LEB128 operand
+		 * followed by a signed LEB128 operand.
+		 */
+		case DW_OP_bregx:
+			operand1 = _dwarf_decode_uleb128(&p);
+			operand2 = _dwarf_decode_sleb128(&p);
+			break;
+
+		/*
+		 * Operation with an unsigned LEB128 operand
+		 * representing the size of a block, followed
+		 * by the block content.
+		 *
+		 * Store the size of the block in the operand1
+		 * and a pointer to the block in the operand2.
+		 */
+		case DW_OP_implicit_value:
+		case DW_OP_GNU_entry_value:
+			operand1 = _dwarf_decode_uleb128(&p);
+			operand2 = (Dwarf_Unsigned) (uintptr_t) p;
+			p += operand1;
+			break;
+
+		/* Target address size operand. */
+		case DW_OP_addr:
+		case DW_OP_GNU_addr_index:
+		case DW_OP_GNU_const_index:
+			operand1 = dbg->decode(&p, pointer_size);
+			break;
+
+		/* Offset size operand. */
+		case DW_OP_call_ref:
+			operand1 = dbg->decode(&p, offset_size);
+			break;
+
+		/*
+		 * The first byte is address byte length, followed by
+		 * the address value. If the length is 0, the address
+		 * size is the same as target pointer size.
+		 */
+		case DW_OP_GNU_encoded_addr:
+			s = *p++;
+			if (s == 0)
+				s = pointer_size;
+			operand1 = dbg->decode(&p, s);
+			break;
+
+		/*
+		 * Operand1: DIE offset (size depending on DWARF version)
+		 * DWARF2: pointer size
+		 * DWARF{3,4}: offset size
+		 *
+		 * Operand2: SLEB128
+		 */
+		case DW_OP_GNU_implicit_pointer:
+			if (version == 2)
+				operand1 = dbg->decode(&p, pointer_size);
+			else
+				operand1 = dbg->decode(&p, offset_size);
+			operand2 = _dwarf_decode_sleb128(&p);
+			break;
+
+		/*
+		 * Operand1: DIE offset (ULEB128)
+		 * Operand2: pointer to a block. The block's first byte
+		 * is its size.
+		 */
+		case DW_OP_GNU_const_type:
+			operand1 = _dwarf_decode_uleb128(&p);
+			operand2 = (Dwarf_Unsigned) (uintptr_t) p;
+			s = *p++;
+			p += s;
+			break;
+
+		/* All other operations cause an error. */
+		default:
+			count = -1;
+			goto done;
+		}
+
+		if (lbuf != NULL) {
+			lbuf->ld_s[count].lr_number = operand1;
+			lbuf->ld_s[count].lr_number2 = operand2;
+		}
+
+		count++;
+	}
+
+done:
+	return (count);
+}
+
+int
+_dwarf_loc_expr_add_atom(Dwarf_Debug dbg, uint8_t *out, uint8_t *end,
+    Dwarf_Small atom, Dwarf_Unsigned operand1, Dwarf_Unsigned operand2,
+    int *length, Dwarf_Error *error)
+{
+	uint8_t buf[64];
+	uint8_t *p, *pe;
+	uint64_t offset;
+	int len;
+
+	if (out != NULL && end != NULL) {
+		p = out;
+		pe = end;
+	} else {
+		p = out = buf;
+		pe = &buf[sizeof(buf)];
+	}
+
+	switch (atom) {
+	/* Operations with no operands. */
+	case DW_OP_deref:
+	case DW_OP_reg0:
+	case DW_OP_reg1:
+	case DW_OP_reg2:
+	case DW_OP_reg3:
+	case DW_OP_reg4:
+	case DW_OP_reg5:
+	case DW_OP_reg6:
+	case DW_OP_reg7:
+	case DW_OP_reg8:
+	case DW_OP_reg9:
+	case DW_OP_reg10:
+	case DW_OP_reg11:
+	case DW_OP_reg12:
+	case DW_OP_reg13:
+	case DW_OP_reg14:
+	case DW_OP_reg15:
+	case DW_OP_reg16:
+	case DW_OP_reg17:
+	case DW_OP_reg18:
+	case DW_OP_reg19:
+	case DW_OP_reg20:
+	case DW_OP_reg21:
+	case DW_OP_reg22:
+	case DW_OP_reg23:
+	case DW_OP_reg24:
+	case DW_OP_reg25:
+	case DW_OP_reg26:
+	case DW_OP_reg27:
+	case DW_OP_reg28:
+	case DW_OP_reg29:
+	case DW_OP_reg30:
+	case DW_OP_reg31:
+
+	case DW_OP_lit0:
+	case DW_OP_lit1:
+	case DW_OP_lit2:
+	case DW_OP_lit3:
+	case DW_OP_lit4:
+	case DW_OP_lit5:
+	case DW_OP_lit6:
+	case DW_OP_lit7:
+	case DW_OP_lit8:
+	case DW_OP_lit9:
+	case DW_OP_lit10:
+	case DW_OP_lit11:
+	case DW_OP_lit12:
+	case DW_OP_lit13:
+	case DW_OP_lit14:
+	case DW_OP_lit15:
+	case DW_OP_lit16:
+	case DW_OP_lit17:
+	case DW_OP_lit18:
+	case DW_OP_lit19:
+	case DW_OP_lit20:
+	case DW_OP_lit21:
+	case DW_OP_lit22:
+	case DW_OP_lit23:
+	case DW_OP_lit24:
+	case DW_OP_lit25:
+	case DW_OP_lit26:
+	case DW_OP_lit27:
+	case DW_OP_lit28:
+	case DW_OP_lit29:
+	case DW_OP_lit30:
+	case DW_OP_lit31:
+
+	case DW_OP_dup:
+	case DW_OP_drop:
+
+	case DW_OP_over:
+
+	case DW_OP_swap:
+	case DW_OP_rot:
+	case DW_OP_xderef:
+
+	case DW_OP_abs:
+	case DW_OP_and:
+	case DW_OP_div:
+	case DW_OP_minus:
+	case DW_OP_mod:
+	case DW_OP_mul:
+	case DW_OP_neg:
+	case DW_OP_not:
+	case DW_OP_or:
+	case DW_OP_plus:
+
+	case DW_OP_shl:
+	case DW_OP_shr:
+	case DW_OP_shra:
+	case DW_OP_xor:
+
+	case DW_OP_eq:
+	case DW_OP_ge:
+	case DW_OP_gt:
+	case DW_OP_le:
+	case DW_OP_lt:
+	case DW_OP_ne:
+
+	case DW_OP_nop:
+	case DW_OP_GNU_push_tls_address:
+		*p++ = atom;
+		break;
+
+	/* Operations with 1-byte operands. */
+	case DW_OP_const1u:
+	case DW_OP_const1s:
+	case DW_OP_pick:
+	case DW_OP_deref_size:
+	case DW_OP_xderef_size:
+		*p++ = atom;
+		*p++ = (uint8_t) operand1;
+		break;
+
+	/* Operations with 2-byte operands. */
+	case DW_OP_const2u:
+	case DW_OP_const2s:
+	case DW_OP_bra:
+	case DW_OP_skip:
+		*p++ = atom;
+		offset = 0;
+		dbg->write(p, &offset, operand1, 2);
+		p += 2;
+		break;
+
+	/* Operations with 4-byte operands. */
+	case DW_OP_const4u:
+	case DW_OP_const4s:
+		*p++ = atom;
+		offset = 0;
+		dbg->write(p, &offset, operand1, 4);
+		p += 4;
+		break;
+
+	/* Operations with 8-byte operands. */
+	case DW_OP_const8u:
+	case DW_OP_const8s:
+		*p++ = atom;
+		offset = 0;
+		dbg->write(p, &offset, operand1, 8);
+		p += 8;
+		break;
+
+	/* Operations with an unsigned LEB128 operand. */
+	case DW_OP_constu:
+	case DW_OP_plus_uconst:
+	case DW_OP_regx:
+	case DW_OP_piece:
+		*p++ = atom;
+		len = _dwarf_write_uleb128(p, pe, operand1);
+		assert(len > 0);
+		p += len;
+		break;
+
+	/* Operations with a signed LEB128 operand. */
+	case DW_OP_consts:
+	case DW_OP_breg0:
+	case DW_OP_breg1:
+	case DW_OP_breg2:
+	case DW_OP_breg3:
+	case DW_OP_breg4:
+	case DW_OP_breg5:
+	case DW_OP_breg6:
+	case DW_OP_breg7:
+	case DW_OP_breg8:
+	case DW_OP_breg9:
+	case DW_OP_breg10:
+	case DW_OP_breg11:
+	case DW_OP_breg12:
+	case DW_OP_breg13:
+	case DW_OP_breg14:
+	case DW_OP_breg15:
+	case DW_OP_breg16:
+	case DW_OP_breg17:
+	case DW_OP_breg18:
+	case DW_OP_breg19:
+	case DW_OP_breg20:
+	case DW_OP_breg21:
+	case DW_OP_breg22:
+	case DW_OP_breg23:
+	case DW_OP_breg24:
+	case DW_OP_breg25:
+	case DW_OP_breg26:
+	case DW_OP_breg27:
+	case DW_OP_breg28:
+	case DW_OP_breg29:
+	case DW_OP_breg30:
+	case DW_OP_breg31:
+	case DW_OP_fbreg:
+		*p++ = atom;
+		len = _dwarf_write_sleb128(p, pe, operand1);
+		assert(len > 0);
+		p += len;
+		break;
+
+	/*
+	 * Operations with an unsigned LEB128 operand
+	 * followed by a signed LEB128 operand.
+	 */
+	case DW_OP_bregx:
+		*p++ = atom;
+		len = _dwarf_write_uleb128(p, pe, operand1);
+		assert(len > 0);
+		p += len;
+		len = _dwarf_write_sleb128(p, pe, operand2);
+		assert(len > 0);
+		p += len;
+		break;
+
+	/* Target address size operand. */
+	case DW_OP_addr:
+		*p++ = atom;
+		offset = 0;
+		dbg->write(p, &offset, operand1, dbg->dbg_pointer_size);
+		p += dbg->dbg_pointer_size;
+		break;
+
+	/* All other operations cause an error. */
+	default:
+		DWARF_SET_ERROR(dbg, error, DW_DLE_LOC_EXPR_BAD);
+		return (DW_DLE_LOC_EXPR_BAD);
+	}
+
+	if (length)
+		*length = p - out;
+
+	return (DW_DLE_NONE);
+}
+
+int
+_dwarf_loc_fill_locdesc(Dwarf_Debug dbg, Dwarf_Locdesc *llbuf, uint8_t *in,
+    uint64_t in_len, uint8_t pointer_size, uint8_t offset_size,
+    uint8_t version, Dwarf_Error *error)
+{
+	int num;
+
+	assert(llbuf != NULL);
+	assert(in != NULL);
+	assert(in_len > 0);
+
+	/* Compute the number of locations. */
+	if ((num = _dwarf_loc_fill_loc(dbg, NULL, pointer_size, offset_size,
+	    version, in, in_len)) < 0) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_LOC_EXPR_BAD);
+		return (DW_DLE_LOC_EXPR_BAD);
+	}
+
+	llbuf->ld_cents = num;
+	if (num <= 0)
+		return (DW_DLE_NONE);
+
+	if ((llbuf->ld_s = calloc(num, sizeof(Dwarf_Loc))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+
+	(void) _dwarf_loc_fill_loc(dbg, llbuf, pointer_size, offset_size,
+	    version, in, in_len);
+
+	return (DW_DLE_NONE);
+}
+
+int
+_dwarf_loc_fill_locexpr(Dwarf_Debug dbg, Dwarf_Locdesc **ret_llbuf, uint8_t *in,
+    uint64_t in_len, uint8_t pointer_size, uint8_t offset_size,
+    uint8_t version, Dwarf_Error *error)
+{
+	Dwarf_Locdesc *llbuf;
+	int ret;
+
+	if ((llbuf = malloc(sizeof(Dwarf_Locdesc))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+	llbuf->ld_lopc = 0;
+	llbuf->ld_hipc = ~0ULL;
+	llbuf->ld_s = NULL;
+
+	ret = _dwarf_loc_fill_locdesc(dbg, llbuf, in, in_len, pointer_size,
+	    offset_size, version, error);
+	if (ret != DW_DLE_NONE) {
+		free(llbuf);
+		return (ret);
+	}
+
+	*ret_llbuf = llbuf;
+
+	return (ret);
+}
+
+int
+_dwarf_loc_add(Dwarf_Die die, Dwarf_Attribute at, Dwarf_Error *error)
+{
+	Dwarf_Debug dbg;
+	Dwarf_CU cu;
+	int ret;
+
+	assert(at->at_ld == NULL);
+	assert(at->u[1].u8p != NULL);
+	assert(at->u[0].u64 > 0);
+
+	cu = die->die_cu;
+	assert(cu != NULL);
+
+	dbg = cu->cu_dbg;
+	assert(dbg != NULL);
+
+	ret = _dwarf_loc_fill_locexpr(dbg, &at->at_ld, at->u[1].u8p,
+	    at->u[0].u64, cu->cu_pointer_size, cu->cu_length_size == 4 ? 4 : 8,
+	    cu->cu_version, error);
+
+	return (ret);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/libdwarf_loclist.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,165 @@
+/*-
+ * Copyright (c) 2009,2011 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: libdwarf_loclist.c 3061 2014-06-02 00:42:41Z kaiwang27 $");
+
+static int
+_dwarf_loclist_add_locdesc(Dwarf_Debug dbg, Dwarf_CU cu, Dwarf_Section *ds,
+    Dwarf_Unsigned *off, Dwarf_Locdesc **ld, Dwarf_Signed *ldlen,
+    Dwarf_Unsigned *total_len, Dwarf_Error *error)
+{
+	uint64_t start, end;
+	int i, len, ret;
+
+	if (total_len != NULL)
+		*total_len = 0;
+
+	for (i = 0; *off < ds->ds_size; i++) {
+		start = dbg->read(ds->ds_data, off, cu->cu_pointer_size);
+		end = dbg->read(ds->ds_data, off, cu->cu_pointer_size);
+		if (ld != NULL) {
+			ld[i]->ld_lopc = start;
+			ld[i]->ld_hipc = end;
+		}
+
+		if (total_len != NULL)
+			*total_len += 2 * cu->cu_pointer_size;
+
+		/* Check if it is the end entry. */
+		if (start == 0 && end ==0) {
+			i++;
+			break;
+		}
+
+		/* Check if it is base-select entry. */
+		if ((cu->cu_pointer_size == 4 && start == ~0U) ||
+		    (cu->cu_pointer_size == 8 && start == ~0ULL))
+			continue;
+
+		/* Otherwise it's normal entry. */
+		len = dbg->read(ds->ds_data, off, 2);
+		if (*off + len > ds->ds_size) {
+			DWARF_SET_ERROR(dbg, error,
+			    DW_DLE_DEBUG_LOC_SECTION_SHORT);
+			return (DW_DLE_DEBUG_LOC_SECTION_SHORT);
+		}
+
+		if (total_len != NULL)
+			*total_len += len;
+
+		if (ld != NULL) {
+			ret = _dwarf_loc_fill_locdesc(dbg, ld[i],
+			    ds->ds_data + *off, len, cu->cu_pointer_size,
+			    cu->cu_length_size == 4 ? 4 : 8, cu->cu_version,
+			    error);
+			if (ret != DW_DLE_NONE)
+				return (ret);
+		}
+
+		*off += len;
+	}
+
+	if (ldlen != NULL)
+		*ldlen = i;
+
+	return (DW_DLE_NONE);
+}
+
+int
+_dwarf_loclist_find(Dwarf_Debug dbg, Dwarf_CU cu, uint64_t lloff,
+    Dwarf_Locdesc ***ret_llbuf, Dwarf_Signed *listlen,
+    Dwarf_Unsigned *entry_len, Dwarf_Error *error)
+{
+	Dwarf_Locdesc **llbuf;
+	Dwarf_Section *ds;
+	Dwarf_Signed ldlen;
+	Dwarf_Unsigned off;
+	int i, ret;
+
+	if ((ds = _dwarf_find_section(dbg, ".debug_loc")) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLE_NO_ENTRY);
+	}
+
+	if (lloff >= ds->ds_size) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLE_NO_ENTRY);
+	}
+
+	/* Get the number of locdesc the first round. */
+	off = lloff;
+	ret = _dwarf_loclist_add_locdesc(dbg, cu, ds, &off, NULL, &ldlen,
+	    NULL, error);
+	if (ret != DW_DLE_NONE)
+		return (ret);
+
+	if (ldlen == 0)
+		return (DW_DLE_NO_ENTRY);
+
+	/*
+	 * Dwarf_Locdesc list memory is allocated in this way (one more level
+	 * of indirect) to make the loclist API be compatible with SGI libdwarf.
+	 */
+	if ((llbuf = calloc(ldlen, sizeof(Dwarf_Locdesc *))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+	for (i = 0; i < ldlen; i++) {
+		if ((llbuf[i] = calloc(1, sizeof(Dwarf_Locdesc))) == NULL) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+			ret = DW_DLE_MEMORY;
+			goto fail_cleanup;
+		}
+	}
+
+	off = lloff;
+
+	/* Fill in locdesc. */
+	ret = _dwarf_loclist_add_locdesc(dbg, cu, ds, &off, llbuf, NULL,
+	    entry_len, error);
+	if (ret != DW_DLE_NONE)
+		goto fail_cleanup;
+
+	*ret_llbuf = llbuf;
+	*listlen = ldlen;
+
+	return (DW_DLE_NONE);
+
+fail_cleanup:
+
+	if (llbuf != NULL) {
+		for (i = 0; i < ldlen; i++) {
+			if (llbuf[i]->ld_s)
+				free(llbuf[i]->ld_s);
+			free(llbuf[i]);
+		}
+		free(llbuf);
+	}
+
+	return (ret);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/libdwarf_macinfo.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,254 @@
+/*-
+ * Copyright (c) 2009-2011 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: libdwarf_macinfo.c 2974 2013-12-23 06:46:22Z kaiwang27 $");
+
+#define	_FILEINDEX_STACK_SIZE	16384
+
+static int
+_dwarf_macinfo_parse(Dwarf_Debug dbg, Dwarf_Section *ds, uint64_t *off,
+    Dwarf_Macro_Details *dmd, Dwarf_Unsigned *cnt, Dwarf_Error *error)
+{
+	Dwarf_Unsigned lineno;
+	Dwarf_Signed fileindex[_FILEINDEX_STACK_SIZE];
+	char *p;
+	int i, type, sp;
+
+	i = 0;
+	sp = 0;
+	fileindex[sp] = -1;
+	while (*off < ds->ds_size) {
+
+		if (dmd != NULL)
+			dmd[i].dmd_offset = *off;
+
+		type = dbg->read(ds->ds_data, off, 1);
+
+		if (dmd != NULL) {
+			dmd[i].dmd_type = type;
+			dmd[i].dmd_fileindex = fileindex[sp];
+		}
+
+		switch (type) {
+		case 0:
+			break;
+		case DW_MACINFO_define:
+		case DW_MACINFO_undef:
+		case DW_MACINFO_vendor_ext:
+			lineno = _dwarf_read_uleb128(ds->ds_data, off);
+			p = (char *) ds->ds_data;
+			if (dmd != NULL) {
+				dmd[i].dmd_lineno = lineno;
+				dmd[i].dmd_macro = p + *off;
+
+			}
+			while (p[(*off)++] != '\0')
+				;
+			break;
+		case DW_MACINFO_start_file:
+			lineno = _dwarf_read_uleb128(ds->ds_data, off);
+			if (sp >= _FILEINDEX_STACK_SIZE - 1) {
+				assert(0);
+			}
+			fileindex[++sp] = _dwarf_read_uleb128(ds->ds_data, off);
+			if (dmd != NULL) {
+				dmd[i].dmd_lineno = lineno;
+				dmd[i].dmd_fileindex = fileindex[sp];
+			}
+			break;
+		case DW_MACINFO_end_file:
+			if (sp > 0) {
+				sp--;
+				break;
+			}
+			/* FALLTHROUGH */
+		default:
+			DWARF_SET_ERROR(dbg, error,
+			    DW_DLE_DEBUG_MACRO_INCONSISTENT);
+			return (DW_DLE_DEBUG_MACRO_INCONSISTENT);
+		}
+
+		i++;
+
+		if (type == 0)
+			break;
+	}
+
+	if (cnt != NULL)
+		*cnt = i;
+
+	return (DW_DLE_NONE);
+}
+
+void
+_dwarf_macinfo_cleanup(Dwarf_Debug dbg)
+{
+	Dwarf_MacroSet ms, tms;
+
+	if (STAILQ_EMPTY(&dbg->dbg_mslist))
+		return;
+
+	STAILQ_FOREACH_SAFE(ms, &dbg->dbg_mslist, ms_next, tms) {
+		STAILQ_REMOVE(&dbg->dbg_mslist, ms, _Dwarf_MacroSet, ms_next);
+		if (ms->ms_mdlist)
+			free(ms->ms_mdlist);
+		free(ms);
+	}
+}
+
+int
+_dwarf_macinfo_init(Dwarf_Debug dbg, Dwarf_Error *error)
+{
+	Dwarf_MacroSet ms;
+	Dwarf_Unsigned cnt;
+	Dwarf_Section *ds;
+	uint64_t offset, entry_off;
+	int ret;
+
+	if ((ds = _dwarf_find_section(dbg, ".debug_macinfo")) == NULL)
+		return (DW_DLE_NONE);
+
+	offset = 0;
+	while (offset < ds->ds_size) {
+
+		entry_off = offset;
+
+		ret = _dwarf_macinfo_parse(dbg, ds, &offset, NULL, &cnt, error);
+		if (ret != DW_DLE_NONE)
+			return (ret);
+
+		if (cnt == 0)
+			break;
+
+		if ((ms = calloc(1, sizeof(struct _Dwarf_MacroSet))) == NULL) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+			ret = DW_DLE_MEMORY;
+			goto fail_cleanup;
+		}
+		STAILQ_INSERT_TAIL(&dbg->dbg_mslist, ms, ms_next);
+
+		if ((ms->ms_mdlist = calloc(cnt, sizeof(Dwarf_Macro_Details)))
+		    == NULL) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+			ret = DW_DLE_MEMORY;
+			goto fail_cleanup;
+		}
+
+		ms->ms_cnt = cnt;
+
+		offset = entry_off;
+
+		ret = _dwarf_macinfo_parse(dbg, ds, &offset, ms->ms_mdlist,
+		    NULL, error);
+
+		if (ret != DW_DLE_NONE) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+			ret = DW_DLE_MEMORY;
+			goto fail_cleanup;
+		}
+	}
+
+	return (DW_DLE_NONE);
+
+fail_cleanup:
+
+	_dwarf_macinfo_cleanup(dbg);
+
+	return (ret);
+}
+
+int
+_dwarf_macinfo_gen(Dwarf_P_Debug dbg, Dwarf_Error *error)
+{
+	Dwarf_P_Section ds;
+	Dwarf_Macro_Details *md;
+	int i, ret;
+
+	if (dbg->dbgp_mdcnt == 0)
+		return (DW_DLE_NONE);
+
+	/* Create .debug_frame section. */
+	RCHECK(_dwarf_section_init(dbg, &ds, ".debug_macinfo", 0, error));
+
+	/* Write the list of Dwarf_Macro_Details. */
+	for (i = 0; (Dwarf_Unsigned) i < dbg->dbgp_mdcnt; i++) {
+		md = &dbg->dbgp_mdlist[i];
+		md->dmd_offset = ds->ds_size;
+		RCHECK(WRITE_VALUE(md->dmd_type, 1));
+		switch (md->dmd_type) {
+		case DW_MACINFO_define:
+		case DW_MACINFO_undef:
+		case DW_MACINFO_vendor_ext:
+			RCHECK(WRITE_ULEB128(md->dmd_lineno));
+			assert(md->dmd_macro != NULL);
+			RCHECK(WRITE_STRING(md->dmd_macro));
+			break;
+		case DW_MACINFO_start_file:
+			RCHECK(WRITE_ULEB128(md->dmd_lineno));
+			RCHECK(WRITE_ULEB128(md->dmd_fileindex));
+			break;
+		case DW_MACINFO_end_file:
+			break;
+		default:
+			assert(0);
+			break;
+		}
+	}
+	RCHECK(WRITE_VALUE(0, 1));
+
+	/* Inform application the creation of .debug_macinfo ELF section. */
+	RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error));
+
+	return (DW_DLE_NONE);
+
+gen_fail:
+	_dwarf_section_free(dbg, &ds);
+
+	return (ret);
+}
+
+void
+_dwarf_macinfo_pro_cleanup(Dwarf_P_Debug dbg)
+{
+	Dwarf_Macro_Details *md;
+	int i;
+
+	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
+	if (dbg->dbgp_mdlist == NULL)
+		return;
+
+	assert(dbg->dbgp_mdcnt > 0);
+	for (i = 0; (Dwarf_Unsigned) i < dbg->dbgp_mdcnt; i++) {
+		md = &dbg->dbgp_mdlist[i];
+		if (md->dmd_macro)
+			free(md->dmd_macro);
+	}
+	free(dbg->dbgp_mdlist);
+	dbg->dbgp_mdlist = NULL;
+	dbg->dbgp_mdcnt = 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/libdwarf_nametbl.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,253 @@
+/*-
+ * Copyright (c) 2009,2010 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: libdwarf_nametbl.c 3029 2014-04-21 23:26:02Z kaiwang27 $");
+
+void
+_dwarf_nametbl_cleanup(Dwarf_NameSec *nsp)
+{
+	Dwarf_NameSec ns;
+	Dwarf_NameTbl nt, tnt;
+	Dwarf_NamePair np, tnp;
+
+	assert(nsp != NULL);
+	if ((ns = *nsp) == NULL)
+		return;
+
+	STAILQ_FOREACH_SAFE(nt, &ns->ns_ntlist, nt_next, tnt) {
+		STAILQ_FOREACH_SAFE(np, &nt->nt_nplist, np_next, tnp) {
+			STAILQ_REMOVE(&nt->nt_nplist, np, _Dwarf_NamePair,
+			    np_next);
+			free(np);
+		}
+		STAILQ_REMOVE(&ns->ns_ntlist, nt, _Dwarf_NameTbl, nt_next);
+		free(nt);
+	}
+	if (ns->ns_array)
+		free(ns->ns_array);
+	free(ns);
+	*nsp = NULL;
+}
+
+int
+_dwarf_nametbl_init(Dwarf_Debug dbg, Dwarf_NameSec *namesec, Dwarf_Section *ds,
+    Dwarf_Error *error)
+{
+	Dwarf_CU cu;
+	Dwarf_NameSec ns;
+	Dwarf_NameTbl nt;
+	Dwarf_NamePair np;
+	uint64_t offset, dwarf_size, length, cuoff;
+	char *p;
+	int i, ret;
+
+	assert(*namesec == NULL);
+
+	if ((ns = malloc(sizeof(struct _Dwarf_NameSec))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+	STAILQ_INIT(&ns->ns_ntlist);
+	ns->ns_array = NULL;
+	ns->ns_len = 0;
+
+	offset = 0;
+	while (offset < ds->ds_size) {
+
+		/* Allocate a new name table. */
+		if ((nt = malloc(sizeof(struct _Dwarf_NameTbl))) == NULL) {
+			ret = DW_DLE_MEMORY;
+			DWARF_SET_ERROR(dbg, error, ret);
+			goto fail_cleanup;
+		}
+		STAILQ_INIT(&nt->nt_nplist);
+		STAILQ_INSERT_TAIL(&ns->ns_ntlist, nt, nt_next);
+
+		/* Read in the table header. */
+		length = dbg->read(ds->ds_data, &offset, 4);
+		if (length == 0xffffffff) {
+			dwarf_size = 8;
+			length = dbg->read(ds->ds_data, &offset, 8);
+		} else
+			dwarf_size = 4;
+
+		nt->nt_length = length;
+		/* FIXME: verify version */
+		nt->nt_version = dbg->read(ds->ds_data, &offset, 2);
+		nt->nt_cu_offset = dbg->read(ds->ds_data, &offset, dwarf_size);
+		nt->nt_cu_length = dbg->read(ds->ds_data, &offset, dwarf_size);
+
+		if (!dbg->dbg_info_loaded) {
+			ret = _dwarf_info_load(dbg, 1, 1, error);
+			if (ret != DW_DLE_NONE)
+				goto fail_cleanup;
+		}
+
+		/* Find the referenced CU. */
+		STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {
+			if (cu->cu_offset == nt->nt_cu_offset)
+				break;
+		}
+		nt->nt_cu = cu;	/* FIXME: Check if NULL here */
+
+		/* Add name pairs. */
+		while (offset < ds->ds_size) {
+			cuoff = dbg->read(ds->ds_data, &offset, dwarf_size);
+			if (cuoff == 0)
+				break;
+			if ((np = malloc(sizeof(struct _Dwarf_NamePair))) ==
+			    NULL) {
+				ret = DW_DLE_MEMORY;
+				DWARF_SET_ERROR(dbg, error, ret);
+				goto fail_cleanup;
+			}
+			np->np_nt = nt;
+			np->np_offset = cuoff;
+			p = (char *) ds->ds_data;
+			np->np_name = &p[offset];
+			while (p[offset++] != '\0')
+				;
+			STAILQ_INSERT_TAIL(&nt->nt_nplist, np, np_next);
+			ns->ns_len++;
+		}
+	}
+
+	/* Build array of name pairs from all tables. */
+	if (ns->ns_len > 0) {
+		if ((ns->ns_array = malloc(sizeof(Dwarf_NamePair) *
+		    ns->ns_len)) == NULL) {
+			ret = DW_DLE_MEMORY;
+			DWARF_SET_ERROR(dbg, error, ret);
+			goto fail_cleanup;
+		}
+
+		i = 0;
+		STAILQ_FOREACH(nt, &ns->ns_ntlist, nt_next) {
+			STAILQ_FOREACH(np, &nt->nt_nplist, np_next)
+				ns->ns_array[i++] = np;
+		}
+		assert((Dwarf_Unsigned)i == ns->ns_len);
+	}
+
+	*namesec = ns;
+
+	return (DW_DLE_NONE);
+
+fail_cleanup:
+
+	_dwarf_nametbl_cleanup(&ns);
+
+	return (ret);
+}
+
+int
+_dwarf_nametbl_gen(Dwarf_P_Debug dbg, const char *name, Dwarf_NameTbl nt,
+    Dwarf_Error *error)
+{
+	Dwarf_P_Section ds;
+	Dwarf_Rel_Section drs;
+	Dwarf_NamePair np;
+	uint64_t offset;
+	int ret;
+
+	assert(dbg != NULL && name != NULL);
+	if (nt == NULL || STAILQ_EMPTY(&nt->nt_nplist))
+		return (DW_DLE_NONE);
+
+	nt->nt_length = 0;
+	nt->nt_version = 2;
+	nt->nt_cu = STAILQ_FIRST(&dbg->dbg_cu);
+	assert(nt->nt_cu != NULL);
+	nt->nt_cu_offset = nt->nt_cu->cu_offset;
+	nt->nt_cu_length = nt->nt_cu->cu_length;
+
+	/* Create name lookup section. */
+	if ((ret = _dwarf_section_init(dbg, &ds, name, 0, error)) !=
+	    DW_DLE_NONE)
+		goto gen_fail0;
+
+	/* Create relocation section for the name lookup section. */
+	RCHECK(_dwarf_reloc_section_init(dbg, &drs, ds, error));
+
+	/* Write table header. */
+	RCHECK(WRITE_VALUE(nt->nt_length, 4));
+	RCHECK(WRITE_VALUE(nt->nt_version, 2));
+	RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc, 4,
+	    ds->ds_size, 0, nt->nt_cu_offset, ".debug_info", error));
+	RCHECK(WRITE_VALUE(nt->nt_cu_length, 4));
+
+	/* Write tuples. */
+	STAILQ_FOREACH(np, &nt->nt_nplist, np_next) {
+		assert(np->np_die != NULL);
+		np->np_offset = np->np_die->die_offset;
+		RCHECK(WRITE_VALUE(np->np_offset, 4));
+		RCHECK(WRITE_STRING(np->np_name));
+	}
+	RCHECK(WRITE_VALUE(0, 4));
+
+	/* Fill in the length field. */
+	nt->nt_length = ds->ds_size - 4;
+	offset = 0;
+	dbg->write(ds->ds_data, &offset, nt->nt_length, 4);
+
+	/* Inform application the creation of name lookup ELF section. */
+	RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error));
+
+	/* Finalize relocation section for the name lookup section. */
+	RCHECK(_dwarf_reloc_section_finalize(dbg, drs, error));
+
+	return (DW_DLE_NONE);
+
+gen_fail:
+	_dwarf_reloc_section_free(dbg, &drs);
+
+gen_fail0:
+	_dwarf_section_free(dbg, &ds);
+
+	return (ret);
+}
+
+void
+_dwarf_nametbl_pro_cleanup(Dwarf_NameTbl *ntp)
+{
+	Dwarf_NameTbl nt;
+	Dwarf_NamePair np, tnp;
+
+	assert(ntp != NULL);
+	if ((nt = *ntp) == NULL)
+		return;
+
+	STAILQ_FOREACH_SAFE(np, &nt->nt_nplist, np_next, tnp) {
+		STAILQ_REMOVE(&nt->nt_nplist, np, _Dwarf_NamePair, np_next);
+		if (np->np_name)
+			free(np->np_name);
+		free(np);
+	}
+	free(nt);
+	*ntp = NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/libdwarf_ranges.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,152 @@
+/*-
+ * Copyright (c) 2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: libdwarf_ranges.c 2972 2013-12-23 06:46:04Z kaiwang27 $");
+
+static int
+_dwarf_ranges_parse(Dwarf_Debug dbg, Dwarf_CU cu, Dwarf_Section *ds,
+    uint64_t off, Dwarf_Ranges *rg, Dwarf_Unsigned *cnt)
+{
+	Dwarf_Unsigned start, end;
+	int i;
+
+	i = 0;
+	while (off < ds->ds_size) {
+
+		start = dbg->read(ds->ds_data, &off, cu->cu_pointer_size);
+		end = dbg->read(ds->ds_data, &off, cu->cu_pointer_size);
+
+		if (rg != NULL) {
+			rg[i].dwr_addr1 = start;
+			rg[i].dwr_addr2 = end;
+			if (start == 0 && end == 0)
+				rg[i].dwr_type = DW_RANGES_END;
+			else if ((start == ~0U && cu->cu_pointer_size == 4) ||
+			    (start == ~0ULL && cu->cu_pointer_size == 8))
+				rg[i].dwr_type = DW_RANGES_ADDRESS_SELECTION;
+			else
+				rg[i].dwr_type = DW_RANGES_ENTRY;
+		}
+
+		i++;
+
+		if (start == 0 && end == 0)
+			break;
+	}
+
+	if (cnt != NULL)
+		*cnt = i;
+
+	return (DW_DLE_NONE);
+}
+
+int
+_dwarf_ranges_find(Dwarf_Debug dbg, uint64_t off, Dwarf_Rangelist *ret_rl)
+{
+	Dwarf_Rangelist rl;
+
+	STAILQ_FOREACH(rl, &dbg->dbg_rllist, rl_next)
+		if (rl->rl_offset == off)
+			break;
+
+	if (rl == NULL)
+		return (DW_DLE_NO_ENTRY);
+
+	if (ret_rl != NULL)
+		*ret_rl = rl;
+
+	return (DW_DLE_NONE);
+}
+
+void
+_dwarf_ranges_cleanup(Dwarf_Debug dbg)
+{
+	Dwarf_Rangelist rl, trl;
+
+	if (STAILQ_EMPTY(&dbg->dbg_rllist))
+		return;
+
+	STAILQ_FOREACH_SAFE(rl, &dbg->dbg_rllist, rl_next, trl) {
+		STAILQ_REMOVE(&dbg->dbg_rllist, rl, _Dwarf_Rangelist, rl_next);
+		if (rl->rl_rgarray)
+			free(rl->rl_rgarray);
+		free(rl);
+	}
+}
+
+int
+_dwarf_ranges_add(Dwarf_Debug dbg, Dwarf_CU cu, uint64_t off,
+    Dwarf_Rangelist *ret_rl, Dwarf_Error *error)
+{
+	Dwarf_Section *ds;
+	Dwarf_Rangelist rl;
+	Dwarf_Unsigned cnt;
+	int ret;
+
+	if ((ds = _dwarf_find_section(dbg, ".debug_ranges")) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
+		return (DW_DLE_NO_ENTRY);
+	}
+
+	if ((rl = malloc(sizeof(struct _Dwarf_Rangelist))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+
+	rl->rl_offset = off;
+
+	ret = _dwarf_ranges_parse(dbg, cu, ds, off, NULL, &cnt);
+	if (ret != DW_DLE_NONE) {
+		free(rl);
+		return (ret);
+	}
+
+	rl->rl_rglen = cnt;
+	if (cnt != 0) {
+		if ((rl->rl_rgarray = calloc(cnt, sizeof(Dwarf_Ranges))) ==
+		    NULL) {
+			free(rl);
+			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+			return (DW_DLE_MEMORY);
+		}
+
+		ret = _dwarf_ranges_parse(dbg, cu, ds, off, rl->rl_rgarray,
+		    NULL);
+		if (ret != DW_DLE_NONE) {
+			free(rl->rl_rgarray);
+			free(rl);
+			return (ret);
+		}
+	} else
+		rl->rl_rgarray = NULL;
+
+	STAILQ_INSERT_TAIL(&dbg->dbg_rllist, rl, rl_next);
+	*ret_rl = rl;
+
+	return (DW_DLE_NONE);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/libdwarf_reloc.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,493 @@
+/*-
+ * Copyright (c) 2010 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: libdwarf_reloc.c 3578 2017-09-14 02:21:28Z emaste $");
+
+Dwarf_Unsigned
+_dwarf_get_reloc_type(Dwarf_P_Debug dbg, int is64)
+{
+
+	assert(dbg != NULL);
+
+	switch (dbg->dbgp_isa) {
+	case DW_ISA_AARCH64:
+		return (is64 ? R_AARCH64_ABS64 : R_AARCH64_ABS32);
+	case DW_ISA_X86:
+		return (R_386_32);
+	case DW_ISA_X86_64:
+		return (is64 ? R_X86_64_64 : R_X86_64_32);
+	case DW_ISA_SPARC:
+		return (is64 ? R_SPARC_UA64 : R_SPARC_UA32);
+	case DW_ISA_PPC:
+		return (R_PPC_ADDR32);
+	case DW_ISA_ARM:
+		return (R_ARM_ABS32);
+	case DW_ISA_MIPS:
+		return (is64 ? R_MIPS_64 : R_MIPS_32);
+	case DW_ISA_RISCV:
+		return (is64 ? R_RISCV_64 : R_RISCV_32);
+	case DW_ISA_IA64:
+		return (is64 ? R_IA_64_DIR64LSB : R_IA_64_DIR32LSB);
+	default:
+		break;
+	}
+	return (0);		/* NOT REACHED */
+}
+
+int
+_dwarf_get_reloc_size(Dwarf_Debug dbg, Dwarf_Unsigned rel_type)
+{
+
+	switch (dbg->dbg_machine) {
+	case EM_NONE:
+		break;
+	case EM_AARCH64:
+		if (rel_type == R_AARCH64_ABS32)
+			return (4);
+		else if (rel_type == R_AARCH64_ABS64)
+			return (8);
+		break;
+	case EM_ARM:
+		if (rel_type == R_ARM_ABS32)
+			return (4);
+		break;
+	case EM_386:
+	case EM_IAMCU:
+		if (rel_type == R_386_32)
+			return (4);
+		break;
+	case EM_X86_64:
+		if (rel_type == R_X86_64_32)
+			return (4);
+		else if (rel_type == R_X86_64_64)
+			return (8);
+		break;
+	case EM_SPARC:
+		if (rel_type == R_SPARC_UA32)
+			return (4);
+		else if (rel_type == R_SPARC_UA64)
+			return (8);
+		break;
+	case EM_PPC:
+		if (rel_type == R_PPC_ADDR32)
+			return (4);
+		break;
+	case EM_MIPS:
+		if (rel_type == R_MIPS_32)
+			return (4);
+		else if (rel_type == R_MIPS_64)
+			return (8);
+		break;
+	case EM_RISCV:
+		if (rel_type == R_RISCV_32)
+			return (4);
+		else if (rel_type == R_RISCV_64)
+			return (8);
+		break;
+	case EM_IA_64:
+		if (rel_type == R_IA_64_SECREL32LSB)
+			return (4);
+		else if (rel_type == R_IA_64_DIR64LSB)
+			return (8);
+		break;
+	default:
+		break;
+	}
+
+	/* unknown relocation. */
+	return (0);
+}
+
+int
+_dwarf_reloc_section_init(Dwarf_P_Debug dbg, Dwarf_Rel_Section *drsp,
+    Dwarf_P_Section ref, Dwarf_Error *error)
+{
+	Dwarf_Rel_Section drs;
+	char name[128];
+	int pseudo;
+
+	assert(dbg != NULL && drsp != NULL && ref != NULL);
+
+	if ((drs = calloc(1, sizeof(struct _Dwarf_Rel_Section))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+
+	drs->drs_ref = ref;
+
+	/*
+	 * FIXME The logic here is most likely wrong. It should
+	 * be the ISA that determines relocation type.
+	 */
+	if (dbg->dbgp_flags & DW_DLC_SIZE_64)
+		drs->drs_addend = 1;
+	else
+		drs->drs_addend = 0;
+
+	if (dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS)
+		pseudo = 1;
+	else
+		pseudo = 0;
+
+	snprintf(name, sizeof(name), "%s%s",
+	    drs->drs_addend ? ".rela" : ".rel", ref->ds_name);
+	if (_dwarf_section_init(dbg, &drs->drs_ds, name, pseudo, error) !=
+	    DW_DLE_NONE) {
+		free(drs);
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+
+	STAILQ_INIT(&drs->drs_dre);
+	STAILQ_INSERT_TAIL(&dbg->dbgp_drslist, drs, drs_next);
+	dbg->dbgp_drscnt++;
+	*drsp = drs;
+
+	return (DW_DLE_NONE);
+}
+
+void
+_dwarf_reloc_section_free(Dwarf_P_Debug dbg, Dwarf_Rel_Section *drsp)
+{
+	Dwarf_Rel_Section drs, tdrs;
+	Dwarf_Rel_Entry dre, tdre;
+
+	assert(dbg != NULL && drsp != NULL);
+
+	if (*drsp == NULL)
+		return;
+
+	STAILQ_FOREACH_SAFE(drs, &dbg->dbgp_drslist, drs_next, tdrs) {
+		if (drs != *drsp)
+			continue;
+		STAILQ_REMOVE(&dbg->dbgp_drslist, drs, _Dwarf_Rel_Section,
+		    drs_next);
+		STAILQ_FOREACH_SAFE(dre, &drs->drs_dre, dre_next, tdre) {
+			STAILQ_REMOVE(&drs->drs_dre, dre, _Dwarf_Rel_Entry,
+			    dre_next);
+			free(dre);
+		}
+		if ((dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) == 0)
+			_dwarf_section_free(dbg, &drs->drs_ds);
+		else {
+			if (drs->drs_ds->ds_name)
+				free(drs->drs_ds->ds_name);
+			free(drs->drs_ds);
+		}
+		free(drs);
+		*drsp = NULL;
+		dbg->dbgp_drscnt--;
+		break;
+	}
+}
+
+int
+_dwarf_reloc_entry_add(Dwarf_P_Debug dbg, Dwarf_Rel_Section drs,
+    Dwarf_P_Section ds, unsigned char type, unsigned char length,
+    Dwarf_Unsigned offset, Dwarf_Unsigned symndx, Dwarf_Unsigned addend,
+    const char *secname, Dwarf_Error *error)
+{
+	Dwarf_Rel_Entry dre;
+	Dwarf_Unsigned reloff;
+	int ret;
+
+	assert(drs != NULL);
+	assert(offset <= ds->ds_size);
+	reloff = offset;
+
+	/*
+	 * If the DW_DLC_SYMBOLIC_RELOCATIONS flag is set or ElfXX_Rel
+	 * is used instead of ELfXX_Rela, we need to write the addend
+	 * in the storage unit to be relocated. Otherwise write 0 in the
+	 * storage unit and the addend will be written into relocation
+	 * section later.
+	 */
+	if ((dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) ||
+	    drs->drs_addend == 0)
+		ret = dbg->write_alloc(&ds->ds_data, &ds->ds_cap, &offset,
+		    addend, length, error);
+	else
+		ret = dbg->write_alloc(&ds->ds_data, &ds->ds_cap, &offset,
+		    0, length, error);
+	if (ret != DW_DLE_NONE)
+		return (ret);
+	if (offset > ds->ds_size)
+		ds->ds_size = offset;
+
+	if ((dre = calloc(1, sizeof(struct _Dwarf_Rel_Entry))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+	STAILQ_INSERT_TAIL(&drs->drs_dre, dre, dre_next);
+	dre->dre_type = type;
+	dre->dre_length = length;
+	dre->dre_offset = reloff;
+	dre->dre_symndx = symndx;
+	dre->dre_addend = addend;
+	dre->dre_secname = secname;
+	drs->drs_drecnt++;
+
+	return (DW_DLE_NONE);
+}
+
+int
+_dwarf_reloc_entry_add_pair(Dwarf_P_Debug dbg, Dwarf_Rel_Section drs,
+    Dwarf_P_Section ds, unsigned char length, Dwarf_Unsigned offset,
+    Dwarf_Unsigned symndx, Dwarf_Unsigned esymndx, Dwarf_Unsigned symoff,
+    Dwarf_Unsigned esymoff, Dwarf_Error *error)
+{
+	Dwarf_Rel_Entry dre;
+	Dwarf_Unsigned reloff;
+	int ret;
+
+	assert(drs != NULL);
+	assert(offset <= ds->ds_size);
+	assert(dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS);
+	reloff = offset;
+
+	/* Write net offset into section stream. */
+	ret = dbg->write_alloc(&ds->ds_data, &ds->ds_cap, &offset,
+	    esymoff - symoff, length, error);
+	if (ret != DW_DLE_NONE)
+		return (ret);
+	if (offset > ds->ds_size)
+		ds->ds_size = offset;
+
+	if ((dre = calloc(2, sizeof(struct _Dwarf_Rel_Entry))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+	STAILQ_INSERT_TAIL(&drs->drs_dre, &dre[0], dre_next);
+	STAILQ_INSERT_TAIL(&drs->drs_dre, &dre[1], dre_next);
+	dre[0].dre_type = dwarf_drt_first_of_length_pair;
+	dre[0].dre_length = length;
+	dre[0].dre_offset = reloff;
+	dre[0].dre_symndx = symndx;
+	dre[0].dre_addend = 0;
+	dre[0].dre_secname = NULL;
+	dre[1].dre_type = dwarf_drt_second_of_length_pair;
+	dre[1].dre_length = length;
+	dre[1].dre_offset = reloff;
+	dre[1].dre_symndx = esymndx;
+	dre[1].dre_addend = 0;
+	dre[1].dre_secname = NULL;
+	drs->drs_drecnt += 2;
+
+	return (DW_DLE_NONE);
+}
+
+int
+_dwarf_reloc_section_finalize(Dwarf_P_Debug dbg, Dwarf_Rel_Section drs,
+    Dwarf_Error *error)
+{
+	Dwarf_P_Section ds;
+	Dwarf_Unsigned unit;
+	int ret, size;
+
+	assert(dbg != NULL && drs != NULL && drs->drs_ds != NULL &&
+	    drs->drs_ref != NULL);
+
+	ds = drs->drs_ds;
+
+	/*
+	 * Calculate the size (in bytes) of the relocation section.
+	 */
+	if (dbg->dbgp_flags & DW_DLC_SIZE_64)
+		unit = drs->drs_addend ? sizeof(Elf64_Rela) : sizeof(Elf64_Rel);
+	else
+		unit = drs->drs_addend ? sizeof(Elf32_Rela) : sizeof(Elf32_Rel);
+	assert(ds->ds_size == 0);
+	size = drs->drs_drecnt * unit;
+
+	/*
+	 * Discard this relocation section if there is no entry in it.
+	 */
+	if (size == 0) {
+		_dwarf_reloc_section_free(dbg, &drs);
+		return (DW_DLE_NONE);
+	}
+
+	/*
+	 * If we are under stream mode, realloc the section data block to
+	 * this size.
+	 */
+	if ((dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) == 0) {
+		ds->ds_cap = size;
+		if ((ds->ds_data = realloc(ds->ds_data, (size_t) ds->ds_cap)) ==
+		    NULL) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+			return (DW_DLE_MEMORY);
+		}
+	}
+
+	/*
+	 * Notify the application the creation of this relocation section.
+	 * Note that the section link here should point to the .symtab
+	 * section, we set it to 0 since we have no way to know .symtab
+	 * section index.
+	 */
+	ret = _dwarf_pro_callback(dbg, ds->ds_name, size,
+	    drs->drs_addend ? SHT_RELA : SHT_REL, 0, 0, drs->drs_ref->ds_ndx,
+	    &ds->ds_symndx, NULL);
+	if (ret < 0) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_ELF_SECT_ERR);
+		return (DW_DLE_ELF_SECT_ERR);
+	}
+	ds->ds_ndx = ret;
+
+	return (DW_DLE_NONE);
+}
+
+int
+_dwarf_reloc_section_gen(Dwarf_P_Debug dbg, Dwarf_Rel_Section drs,
+    Dwarf_Error *error)
+{
+	Dwarf_Rel_Entry dre;
+	Dwarf_P_Section ds;
+	Dwarf_Unsigned type;
+	int ret;
+
+	assert((dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) == 0);
+	assert(drs->drs_ds != NULL && drs->drs_ds->ds_size == 0);
+	assert(!STAILQ_EMPTY(&drs->drs_dre));
+	ds = drs->drs_ds;
+
+	STAILQ_FOREACH(dre, &drs->drs_dre, dre_next) {
+		assert(dre->dre_length == 4 || dre->dre_length == 8);
+		type = _dwarf_get_reloc_type(dbg, dre->dre_length == 8);
+		if (dbg->dbgp_flags & DW_DLC_SIZE_64) {
+			/* Write r_offset (8 bytes) */
+			ret = dbg->write_alloc(&ds->ds_data, &ds->ds_cap,
+			    &ds->ds_size, dre->dre_offset, 8, error);
+			if (ret != DW_DLE_NONE)
+				return (ret);
+			/* Write r_info (8 bytes) */
+			ret = dbg->write_alloc(&ds->ds_data, &ds->ds_cap,
+			    &ds->ds_size, ELF64_R_INFO(dre->dre_symndx, type),
+			    8, error);
+			if (ret != DW_DLE_NONE)
+				return (ret);
+			/* Write r_addend (8 bytes) */
+			if (drs->drs_addend) {
+				ret = dbg->write_alloc(&ds->ds_data,
+				    &ds->ds_cap, &ds->ds_size, dre->dre_addend,
+				    8, error);
+				if (ret != DW_DLE_NONE)
+					return (ret);
+			}
+		} else {
+			/* Write r_offset (4 bytes) */
+			ret = dbg->write_alloc(&ds->ds_data, &ds->ds_cap,
+			    &ds->ds_size, dre->dre_offset, 4, error);
+			if (ret != DW_DLE_NONE)
+				return (ret);
+			/* Write r_info (4 bytes) */
+			ret = dbg->write_alloc(&ds->ds_data, &ds->ds_cap,
+			    &ds->ds_size, ELF32_R_INFO(dre->dre_symndx, type),
+			    4, error);
+			if (ret != DW_DLE_NONE)
+				return (ret);
+			/* Write r_addend (4 bytes) */
+			if (drs->drs_addend) {
+				ret = dbg->write_alloc(&ds->ds_data,
+				    &ds->ds_cap, &ds->ds_size, dre->dre_addend,
+				    4, error);
+				if (ret != DW_DLE_NONE)
+					return (ret);
+			}
+		}
+	}
+	assert(ds->ds_size == ds->ds_cap);
+
+	return (DW_DLE_NONE);
+}
+
+int
+_dwarf_reloc_gen(Dwarf_P_Debug dbg, Dwarf_Error *error)
+{
+	Dwarf_Rel_Section drs;
+	Dwarf_Rel_Entry dre;
+	Dwarf_P_Section ds;
+	int ret;
+
+	STAILQ_FOREACH(drs, &dbg->dbgp_drslist, drs_next) {
+		/*
+		 * Update relocation entries: translate any section name
+		 * reference to section symbol index.
+		 */
+		STAILQ_FOREACH(dre, &drs->drs_dre, dre_next) {
+			if (dre->dre_secname == NULL)
+				continue;
+			ds = _dwarf_pro_find_section(dbg, dre->dre_secname);
+			assert(ds != NULL && ds->ds_symndx != 0);
+			dre->dre_symndx = ds->ds_symndx;
+		}
+
+		/*
+		 * Generate ELF relocation section if we are under stream
+		 * mode.
+		 */
+		if ((dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) == 0) {
+			ret = _dwarf_reloc_section_gen(dbg, drs, error);
+			if (ret != DW_DLE_NONE)
+				return (ret);
+		}
+	}
+
+	return (DW_DLE_NONE);
+}
+
+void
+_dwarf_reloc_cleanup(Dwarf_P_Debug dbg)
+{
+	Dwarf_Rel_Section drs, tdrs;
+	Dwarf_Rel_Entry dre, tdre;
+
+	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
+
+	STAILQ_FOREACH_SAFE(drs, &dbg->dbgp_drslist, drs_next, tdrs) {
+		STAILQ_REMOVE(&dbg->dbgp_drslist, drs, _Dwarf_Rel_Section,
+		    drs_next);
+		free(drs->drs_drd);
+		STAILQ_FOREACH_SAFE(dre, &drs->drs_dre, dre_next, tdre) {
+			STAILQ_REMOVE(&drs->drs_dre, dre, _Dwarf_Rel_Entry,
+			    dre_next);
+			free(dre);
+		}
+		if (dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) {
+			if (drs->drs_ds) {
+				if (drs->drs_ds->ds_name)
+					free(drs->drs_ds->ds_name);
+				free(drs->drs_ds);
+			}
+		}
+		free(drs);
+	}
+	dbg->dbgp_drscnt = 0;
+	dbg->dbgp_drspos = NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/libdwarf_rw.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,574 @@
+/*-
+ * Copyright (c) 2007 John Birrell (jb@freebsd.org)
+ * Copyright (c) 2010 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: libdwarf_rw.c 3286 2015-12-31 16:45:46Z emaste $");
+
+uint64_t
+_dwarf_read_lsb(uint8_t *data, uint64_t *offsetp, int bytes_to_read)
+{
+	uint64_t ret;
+	uint8_t *src;
+
+	src = data + *offsetp;
+
+	ret = 0;
+	switch (bytes_to_read) {
+	case 8:
+		ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40;
+		ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56;
+		/* FALLTHROUGH */
+	case 4:
+		ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24;
+		/* FALLTHROUGH */
+	case 2:
+		ret |= ((uint64_t) src[1]) << 8;
+		/* FALLTHROUGH */
+	case 1:
+		ret |= src[0];
+		break;
+	default:
+		return (0);
+	}
+
+	*offsetp += bytes_to_read;
+
+	return (ret);
+}
+
+uint64_t
+_dwarf_decode_lsb(uint8_t **data, int bytes_to_read)
+{
+	uint64_t ret;
+	uint8_t *src;
+
+	src = *data;
+
+	ret = 0;
+	switch (bytes_to_read) {
+	case 8:
+		ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40;
+		ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56;
+		/* FALLTHROUGH */
+	case 4:
+		ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24;
+		/* FALLTHROUGH */
+	case 2:
+		ret |= ((uint64_t) src[1]) << 8;
+		/* FALLTHROUGH */
+	case 1:
+		ret |= src[0];
+		break;
+	default:
+		return (0);
+	}
+
+	*data += bytes_to_read;
+
+	return (ret);
+}
+
+uint64_t
+_dwarf_read_msb(uint8_t *data, uint64_t *offsetp, int bytes_to_read)
+{
+	uint64_t ret;
+	uint8_t *src;
+
+	src = data + *offsetp;
+
+	switch (bytes_to_read) {
+	case 1:
+		ret = src[0];
+		break;
+	case 2:
+		ret = src[1] | ((uint64_t) src[0]) << 8;
+		break;
+	case 4:
+		ret = src[3] | ((uint64_t) src[2]) << 8;
+		ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24;
+		break;
+	case 8:
+		ret = src[7] | ((uint64_t) src[6]) << 8;
+		ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24;
+		ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40;
+		ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56;
+		break;
+	default:
+		return (0);
+	}
+
+	*offsetp += bytes_to_read;
+
+	return (ret);
+}
+
+uint64_t
+_dwarf_decode_msb(uint8_t **data, int bytes_to_read)
+{
+	uint64_t ret;
+	uint8_t *src;
+
+	src = *data;
+
+	ret = 0;
+	switch (bytes_to_read) {
+	case 1:
+		ret = src[0];
+		break;
+	case 2:
+		ret = src[1] | ((uint64_t) src[0]) << 8;
+		break;
+	case 4:
+		ret = src[3] | ((uint64_t) src[2]) << 8;
+		ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24;
+		break;
+	case 8:
+		ret = src[7] | ((uint64_t) src[6]) << 8;
+		ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24;
+		ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40;
+		ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56;
+		break;
+	default:
+		return (0);
+		break;
+	}
+
+	*data += bytes_to_read;
+
+	return (ret);
+}
+
+void
+_dwarf_write_lsb(uint8_t *data, uint64_t *offsetp, uint64_t value,
+    int bytes_to_write)
+{
+	uint8_t *dst;
+
+	dst = data + *offsetp;
+
+	switch (bytes_to_write) {
+	case 8:
+		dst[7] = (value >> 56) & 0xff;
+		dst[6] = (value >> 48) & 0xff;
+		dst[5] = (value >> 40) & 0xff;
+		dst[4] = (value >> 32) & 0xff;
+		/* FALLTHROUGH */
+	case 4:
+		dst[3] = (value >> 24) & 0xff;
+		dst[2] = (value >> 16) & 0xff;
+		/* FALLTHROUGH */
+	case 2:
+		dst[1] = (value >> 8) & 0xff;
+		/* FALLTHROUGH */
+	case 1:
+		dst[0] = value & 0xff;
+		break;
+	default:
+		return;
+	}
+
+	*offsetp += bytes_to_write;
+}
+
+int
+_dwarf_write_lsb_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
+    uint64_t value, int bytes_to_write, Dwarf_Error *error)
+{
+
+	assert(*size > 0);
+
+	while (*offsetp + bytes_to_write > *size) {
+		*size *= 2;
+		*block = realloc(*block, (size_t) *size);
+		if (*block == NULL) {
+			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
+			return (DW_DLE_MEMORY);
+		}
+	}
+
+	_dwarf_write_lsb(*block, offsetp, value, bytes_to_write);
+
+	return (DW_DLE_NONE);
+}
+
+void
+_dwarf_write_msb(uint8_t *data, uint64_t *offsetp, uint64_t value,
+    int bytes_to_write)
+{
+	uint8_t *dst;
+
+	dst = data + *offsetp;
+
+	switch (bytes_to_write) {
+	case 8:
+		dst[7] = value & 0xff;
+		dst[6] = (value >> 8) & 0xff;
+		dst[5] = (value >> 16) & 0xff;
+		dst[4] = (value >> 24) & 0xff;
+		value >>= 32;
+		/* FALLTHROUGH */
+	case 4:
+		dst[3] = value & 0xff;
+		dst[2] = (value >> 8) & 0xff;
+		value >>= 16;
+		/* FALLTHROUGH */
+	case 2:
+		dst[1] = value & 0xff;
+		value >>= 8;
+		/* FALLTHROUGH */
+	case 1:
+		dst[0] = value & 0xff;
+		break;
+	default:
+		return;
+	}
+
+	*offsetp += bytes_to_write;
+}
+
+int
+_dwarf_write_msb_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
+    uint64_t value, int bytes_to_write, Dwarf_Error *error)
+{
+
+	assert(*size > 0);
+
+	while (*offsetp + bytes_to_write > *size) {
+		*size *= 2;
+		*block = realloc(*block, (size_t) *size);
+		if (*block == NULL) {
+			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
+			return (DW_DLE_MEMORY);
+		}
+	}
+
+	_dwarf_write_msb(*block, offsetp, value, bytes_to_write);
+
+	return (DW_DLE_NONE);
+}
+
+int64_t
+_dwarf_read_sleb128(uint8_t *data, uint64_t *offsetp)
+{
+	int64_t ret = 0;
+	uint8_t b;
+	int shift = 0;
+	uint8_t *src;
+
+	src = data + *offsetp;
+
+	do {
+		b = *src++;
+		ret |= ((b & 0x7f) << shift);
+		(*offsetp)++;
+		shift += 7;
+	} while ((b & 0x80) != 0);
+
+	if (shift < 64 && (b & 0x40) != 0)
+		ret |= (-1 << shift);
+
+	return (ret);
+}
+
+int
+_dwarf_write_sleb128(uint8_t *data, uint8_t *end, int64_t val)
+{
+	uint8_t *p;
+
+	p = data;
+
+	for (;;) {
+		if (p >= end)
+			return (-1);
+		*p = val & 0x7f;
+		val >>= 7;
+		if ((val == 0 && (*p & 0x40) == 0) ||
+		    (val == -1 && (*p & 0x40) != 0)) {
+			p++;
+			break;
+		}
+		*p++ |= 0x80;
+	}
+
+	return (p - data);
+}
+
+int
+_dwarf_write_sleb128_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
+    int64_t val, Dwarf_Error *error)
+{
+	int len;
+
+	assert(*size > 0);
+
+	while ((len = _dwarf_write_sleb128(*block + *offsetp, *block + *size,
+	    val)) < 0) {
+		*size *= 2;
+		*block = realloc(*block, (size_t) *size);
+		if (*block == NULL) {
+			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
+			return (DW_DLE_MEMORY);
+		}
+	}
+
+	*offsetp += len;
+
+	return (DW_DLE_NONE);
+}
+
+uint64_t
+_dwarf_read_uleb128(uint8_t *data, uint64_t *offsetp)
+{
+	uint64_t ret = 0;
+	uint8_t b;
+	int shift = 0;
+	uint8_t *src;
+
+	src = data + *offsetp;
+
+	do {
+		b = *src++;
+		ret |= ((b & 0x7f) << shift);
+		(*offsetp)++;
+		shift += 7;
+	} while ((b & 0x80) != 0);
+
+	return (ret);
+}
+
+int
+_dwarf_write_uleb128(uint8_t *data, uint8_t *end, uint64_t val)
+{
+	uint8_t *p;
+
+	p = data;
+
+	do {
+		if (p >= end)
+			return (-1);
+		*p = val & 0x7f;
+		val >>= 7;
+		if (val > 0)
+			*p |= 0x80;
+		p++;
+	} while (val > 0);
+
+	return (p - data);
+}
+
+int
+_dwarf_write_uleb128_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
+    uint64_t val, Dwarf_Error *error)
+{
+	int len;
+
+	assert(*size > 0);
+
+	while ((len = _dwarf_write_uleb128(*block + *offsetp, *block + *size,
+	    val)) < 0) {
+		*size *= 2;
+		*block = realloc(*block, (size_t) *size);
+		if (*block == NULL) {
+			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
+			return (DW_DLE_MEMORY);
+		}
+	}
+
+	*offsetp += len;
+
+	return (DW_DLE_NONE);
+}
+
+int64_t
+_dwarf_decode_sleb128(uint8_t **dp)
+{
+	int64_t ret = 0;
+	uint8_t b;
+	int shift = 0;
+
+	uint8_t *src = *dp;
+
+	do {
+		b = *src++;
+		ret |= ((b & 0x7f) << shift);
+		shift += 7;
+	} while ((b & 0x80) != 0);
+
+	if (shift < 64 && (b & 0x40) != 0)
+		ret |= (-1 << shift);
+
+	*dp = src;
+
+	return (ret);
+}
+
+uint64_t
+_dwarf_decode_uleb128(uint8_t **dp)
+{
+	uint64_t ret = 0;
+	uint8_t b;
+	int shift = 0;
+
+	uint8_t *src = *dp;
+
+	do {
+		b = *src++;
+		ret |= ((b & 0x7f) << shift);
+		shift += 7;
+	} while ((b & 0x80) != 0);
+
+	*dp = src;
+
+	return (ret);
+}
+
+char *
+_dwarf_read_string(void *data, Dwarf_Unsigned size, uint64_t *offsetp)
+{
+	char *ret, *src;
+
+	ret = src = (char *) data + *offsetp;
+
+	while (*src != '\0' && *offsetp < size) {
+		src++;
+		(*offsetp)++;
+	}
+
+	if (*src == '\0' && *offsetp < size)
+		(*offsetp)++;
+
+	return (ret);
+}
+
+void
+_dwarf_write_string(void *data, uint64_t *offsetp, char *string)
+{
+	char *dst;
+
+	dst = (char *) data + *offsetp;
+	strcpy(dst, string);
+	(*offsetp) += strlen(string) + 1;
+}
+
+int
+_dwarf_write_string_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
+    char *string, Dwarf_Error *error)
+{
+	size_t len;
+
+	assert(*size > 0);
+
+	len = strlen(string) + 1;
+	while (*offsetp + len > *size) {
+		*size *= 2;
+		*block = realloc(*block, (size_t) *size);
+		if (*block == NULL) {
+			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
+			return (DW_DLE_MEMORY);
+		}
+	}
+
+	_dwarf_write_string(*block, offsetp, string);
+
+	return (DW_DLE_NONE);
+}
+
+uint8_t *
+_dwarf_read_block(void *data, uint64_t *offsetp, uint64_t length)
+{
+	uint8_t *ret, *src;
+
+	ret = src = (uint8_t *) data + *offsetp;
+
+	(*offsetp) += length;
+
+	return (ret);
+}
+
+void
+_dwarf_write_block(void *data, uint64_t *offsetp, uint8_t *blk,
+    uint64_t length)
+{
+	uint8_t *dst;
+
+	dst = (uint8_t *) data + *offsetp;
+	memcpy(dst, blk, length);
+	(*offsetp) += length;
+}
+
+int
+_dwarf_write_block_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
+    uint8_t *blk, uint64_t length, Dwarf_Error *error)
+{
+
+	assert(*size > 0);
+
+	while (*offsetp + length > *size) {
+		*size *= 2;
+		*block = realloc(*block, (size_t) *size);
+		if (*block == NULL) {
+			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
+			return (DW_DLE_MEMORY);
+		}
+	}
+
+	_dwarf_write_block(*block, offsetp, blk, length);
+
+	return (DW_DLE_NONE);
+}
+
+void
+_dwarf_write_padding(void *data, uint64_t *offsetp, uint8_t byte,
+    uint64_t length)
+{
+	uint8_t *dst;
+
+	dst = (uint8_t *) data + *offsetp;
+	memset(dst, byte, length);
+	(*offsetp) += length;
+}
+
+int
+_dwarf_write_padding_alloc(uint8_t **block, uint64_t *size, uint64_t *offsetp,
+    uint8_t byte, uint64_t cnt, Dwarf_Error *error)
+{
+	assert(*size > 0);
+
+	while (*offsetp + cnt > *size) {
+		*size *= 2;
+		*block = realloc(*block, (size_t) *size);
+		if (*block == NULL) {
+			DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
+			return (DW_DLE_MEMORY);
+		}
+	}
+
+	_dwarf_write_padding(*block, offsetp, byte, cnt);
+
+	return (DW_DLE_NONE);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/libdwarf_sections.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,280 @@
+/*-
+ * Copyright (c) 2010 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: libdwarf_sections.c 3041 2014-05-18 15:11:03Z kaiwang27 $");
+
+#define	_SECTION_INIT_SIZE	128
+
+int
+_dwarf_section_init(Dwarf_P_Debug dbg, Dwarf_P_Section *dsp, const char *name,
+    int pseudo, Dwarf_Error *error)
+{
+	Dwarf_P_Section ds;
+
+	assert(dbg != NULL && dsp != NULL && name != NULL);
+
+	if ((ds = calloc(1, sizeof(struct _Dwarf_P_Section))) == NULL) {
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+
+	if ((ds->ds_name = strdup(name)) == NULL) {
+		free(ds);
+		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+		return (DW_DLE_MEMORY);
+	}
+
+	if (!pseudo) {
+		ds->ds_cap = _SECTION_INIT_SIZE;
+		if ((ds->ds_data = malloc((size_t) ds->ds_cap)) == NULL) {
+			free(ds->ds_name);
+			free(ds);
+			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+			return (DW_DLE_MEMORY);
+		}
+		STAILQ_INSERT_TAIL(&dbg->dbgp_seclist, ds, ds_next);
+		dbg->dbgp_seccnt++;
+	}
+
+	*dsp = ds;
+
+	return (DW_DLE_NONE);
+}
+
+void
+_dwarf_section_free(Dwarf_P_Debug dbg, Dwarf_P_Section *dsp)
+{
+	Dwarf_P_Section ds, tds;
+
+	assert(dbg != NULL && dsp != NULL);
+
+	if (*dsp == NULL)
+		return;
+
+	STAILQ_FOREACH_SAFE(ds, &dbg->dbgp_seclist, ds_next, tds) {
+		if (ds == *dsp) {
+			STAILQ_REMOVE(&dbg->dbgp_seclist, ds, _Dwarf_P_Section,
+			    ds_next);
+			dbg->dbgp_seccnt--;
+			break;
+		}
+	}
+	ds = *dsp;
+	if (ds->ds_name)
+		free(ds->ds_name);
+	if (ds->ds_data)
+		free(ds->ds_data);
+	free(ds);
+	*dsp = NULL;
+}
+
+int
+_dwarf_pro_callback(Dwarf_P_Debug dbg, char *name, int size,
+    Dwarf_Unsigned type, Dwarf_Unsigned flags, Dwarf_Unsigned link,
+    Dwarf_Unsigned info, Dwarf_Unsigned *symndx, int *error)
+{
+	int e, ret, isymndx;
+
+	assert(dbg != NULL && name != NULL && symndx != NULL);
+
+	if (dbg->dbgp_func_b)
+		ret = dbg->dbgp_func_b(name, size, type, flags, link, info,
+		    symndx, &e);
+	else {
+		ret = dbg->dbgp_func(name, size, type, flags, link, info,
+		    &isymndx, &e);
+		*symndx = isymndx;
+	}
+	if (ret < 0) {
+		if (error)
+			*error = e;
+	}
+
+	return (ret);
+}
+
+int
+_dwarf_section_callback(Dwarf_P_Debug dbg, Dwarf_P_Section ds,
+    Dwarf_Unsigned type, Dwarf_Unsigned flags, Dwarf_Unsigned link,
+    Dwarf_Unsigned info, Dwarf_Error *error)
+{
+	int ret, ndx;
+
+	ndx = _dwarf_pro_callback(dbg, ds->ds_name, (int) ds->ds_size,
+	    type, flags, link, info, &ds->ds_symndx, NULL);
+	if (ndx < 0) {
+		ret = DW_DLE_ELF_SECT_ERR;
+		DWARF_SET_ERROR(dbg, error, ret);
+		return (ret);
+	}
+	ds->ds_ndx = ndx;
+
+	return (DW_DLE_NONE);
+}
+
+int
+_dwarf_generate_sections(Dwarf_P_Debug dbg, Dwarf_Error *error)
+{
+	int ret;
+
+	/* Produce .debug_info section. */
+	if ((ret = _dwarf_info_gen(dbg, error)) != DW_DLE_NONE)
+		return (ret);
+
+	/* Produce .debug_abbrev section. */
+	if ((ret = _dwarf_abbrev_gen(dbg, error)) != DW_DLE_NONE)
+		return (ret);
+
+	/* Produce .debug_line section. */
+	if ((ret = _dwarf_lineno_gen(dbg, error)) != DW_DLE_NONE)
+		return (ret);
+
+	/* Produce .debug_frame section. */
+	if ((ret = _dwarf_frame_gen(dbg, error)) != DW_DLE_NONE)
+		return (ret);
+
+	/* Produce .debug_aranges section. */
+	if ((ret = _dwarf_arange_gen(dbg, error)) != DW_DLE_NONE)
+		return (ret);
+
+	/* Produce .debug_macinfo section. */
+	if ((ret = _dwarf_macinfo_gen(dbg, error)) != DW_DLE_NONE)
+		return (ret);
+
+	/* Produce .debug_pubnames section. */
+	if ((ret = _dwarf_nametbl_gen(dbg, ".debug_pubnames", dbg->dbgp_pubs,
+	    error)) != DW_DLE_NONE)
+		return (ret);
+
+	/* Produce .debug_weaknames section. */
+	if ((ret = _dwarf_nametbl_gen(dbg, ".debug_weaknames", dbg->dbgp_weaks,
+	    error)) != DW_DLE_NONE)
+		return (ret);
+
+	/* Produce .debug_funcnames section. */
+	if ((ret = _dwarf_nametbl_gen(dbg, ".debug_funcnames", dbg->dbgp_funcs,
+	    error)) != DW_DLE_NONE)
+		return (ret);
+
+	/* Produce .debug_typenames section. */
+	if ((ret = _dwarf_nametbl_gen(dbg, ".debug_typenames", dbg->dbgp_types,
+	    error)) != DW_DLE_NONE)
+		return (ret);
+
+	/* Produce .debug_varnames section. */
+	if ((ret = _dwarf_nametbl_gen(dbg, ".debug_varnames", dbg->dbgp_vars,
+	    error)) != DW_DLE_NONE)
+		return (ret);
+
+	/* Produce .debug_str section. */
+	if ((ret = _dwarf_strtab_gen(dbg, error)) != DW_DLE_NONE)
+		return (ret);
+
+	/* Finally, update and generate all relocation sections. */
+	if ((ret = _dwarf_reloc_gen(dbg, error)) != DW_DLE_NONE)
+		return (ret);
+
+	/* Set section/relocation iterator to the first element. */
+	dbg->dbgp_secpos = STAILQ_FIRST(&dbg->dbgp_seclist);
+	dbg->dbgp_drspos = STAILQ_FIRST(&dbg->dbgp_drslist);
+	
+	return (DW_DLE_NONE);
+}
+
+Dwarf_Section *
+_dwarf_find_section(Dwarf_Debug dbg, const char *name)
+{
+	Dwarf_Section *ds;
+	Dwarf_Half i;
+
+	assert(dbg != NULL && name != NULL);
+
+	for (i = 0; i < dbg->dbg_seccnt; i++) {
+		ds = &dbg->dbg_section[i];
+		if (ds->ds_name != NULL && !strcmp(ds->ds_name, name))
+			return (ds);
+	}
+
+	return (NULL);
+}
+
+Dwarf_Section *
+_dwarf_find_next_types_section(Dwarf_Debug dbg, Dwarf_Section *ds)
+{
+
+	assert(dbg != NULL);
+
+	if (ds == NULL)
+		return (_dwarf_find_section(dbg, ".debug_types"));
+
+	assert(ds->ds_name != NULL);
+
+	do {
+		ds++;
+		if (ds->ds_name != NULL &&
+		    !strcmp(ds->ds_name, ".debug_types"))
+			return (ds);
+	} while (ds->ds_name != NULL);
+
+	return (NULL);
+}
+
+Dwarf_P_Section
+_dwarf_pro_find_section(Dwarf_P_Debug dbg, const char *name)
+{
+	Dwarf_P_Section ds;
+
+	assert(dbg != NULL && name != NULL);
+
+	STAILQ_FOREACH(ds, &dbg->dbgp_seclist, ds_next) {
+		if (ds->ds_name != NULL && !strcmp(ds->ds_name ,name))
+			return (ds);
+	}
+
+	return (NULL);
+}
+
+void
+_dwarf_section_cleanup(Dwarf_P_Debug dbg)
+{
+	Dwarf_P_Section ds, tds;
+
+	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
+
+	STAILQ_FOREACH_SAFE(ds, &dbg->dbgp_seclist, ds_next, tds) {
+		STAILQ_REMOVE(&dbg->dbgp_seclist, ds, _Dwarf_P_Section,
+		    ds_next);
+		if (ds->ds_name)
+			free(ds->ds_name);
+		if (ds->ds_data)
+			free(ds->ds_data);
+		free(ds);
+	}
+	dbg->dbgp_seccnt = 0;
+	dbg->dbgp_secpos = 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/libdwarf_str.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,159 @@
+/*-
+ * Copyright (c) 2009,2010 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "_libdwarf.h"
+
+ELFTC_VCSID("$Id: libdwarf_str.c 2070 2011-10-27 03:05:32Z jkoshy $");
+
+#define	_INIT_DWARF_STRTAB_SIZE 1024
+
+int
+_dwarf_strtab_add(Dwarf_Debug dbg, char *string, uint64_t *off,
+    Dwarf_Error *error)
+{
+	size_t len;
+
+	assert(dbg != NULL && string != NULL);
+
+	len = strlen(string) + 1;
+	while (dbg->dbg_strtab_size + len > dbg->dbg_strtab_cap) {
+		dbg->dbg_strtab_cap *= 2;
+		dbg->dbg_strtab = realloc(dbg->dbg_strtab,
+		    (size_t) dbg->dbg_strtab_cap);
+		if (dbg->dbg_strtab == NULL) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+			return (DW_DLE_MEMORY);
+		}
+	}
+
+	if (off != NULL)
+		*off = dbg->dbg_strtab_size;
+
+	strncpy(&dbg->dbg_strtab[dbg->dbg_strtab_size], string, len - 1);
+	dbg->dbg_strtab_size += len;
+	dbg->dbg_strtab[dbg->dbg_strtab_size - 1] = '\0';
+
+	return (DW_DLE_NONE);
+}
+
+char *
+_dwarf_strtab_get_table(Dwarf_Debug dbg)
+{
+
+	assert(dbg != NULL);
+
+	return (dbg->dbg_strtab);
+}
+
+int
+_dwarf_strtab_init(Dwarf_Debug dbg, Dwarf_Error *error)
+{
+	Dwarf_Section *ds;
+
+	assert(dbg != NULL);
+
+	if (dbg->dbg_mode == DW_DLC_READ || dbg->dbg_mode == DW_DLC_RDWR) {
+		ds = _dwarf_find_section(dbg, ".debug_str");
+		if (ds == NULL) {
+			dbg->dbg_strtab = NULL;
+			dbg->dbg_strtab_cap = dbg->dbg_strtab_size = 0;
+			return (DW_DLE_NONE);
+		}
+
+		dbg->dbg_strtab_cap = dbg->dbg_strtab_size = ds->ds_size;
+
+		if (dbg->dbg_mode == DW_DLC_RDWR) {
+			if ((dbg->dbg_strtab = malloc((size_t) ds->ds_size)) ==
+			    NULL) {
+				DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+				return (DW_DLE_MEMORY);
+			}
+			memcpy(dbg->dbg_strtab, ds->ds_data, ds->ds_size);
+		} else
+			dbg->dbg_strtab = (char *) ds->ds_data;
+	} else {
+		/* DW_DLC_WRITE */
+
+		dbg->dbg_strtab_cap = _INIT_DWARF_STRTAB_SIZE;
+		dbg->dbg_strtab_size = 0;
+
+		if ((dbg->dbg_strtab = malloc((size_t) dbg->dbg_strtab_cap)) ==
+		    NULL) {
+			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+			return (DW_DLE_MEMORY);
+		}
+
+		dbg->dbg_strtab[0] = '\0';
+	}
+
+	return (DW_DLE_NONE);
+}
+
+void
+_dwarf_strtab_cleanup(Dwarf_Debug dbg)
+{
+
+	assert(dbg != NULL);
+
+	if (dbg->dbg_mode == DW_DLC_RDWR || dbg->dbg_mode == DW_DLC_WRITE)
+		free(dbg->dbg_strtab);
+}
+
+int
+_dwarf_strtab_gen(Dwarf_P_Debug dbg, Dwarf_Error *error)
+{
+	Dwarf_P_Section ds;
+	int ret;
+
+	assert(dbg != NULL);
+
+	if ((ret = _dwarf_section_init(dbg, &ds, ".debug_str", 0, error)) !=
+	    DW_DLE_NONE)
+		return (ret);
+
+	if (dbg->dbg_strtab_size > ds->ds_cap) {
+		ds->ds_data = realloc(ds->ds_data,
+		    (size_t) dbg->dbg_strtab_size);
+		if (ds->ds_data == NULL) {
+			_dwarf_section_free(dbg, &ds);
+			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+			return (DW_DLE_MEMORY);
+		}
+		ds->ds_cap = dbg->dbg_strtab_size;
+	}
+
+	memcpy(ds->ds_data, dbg->dbg_strtab, dbg->dbg_strtab_size);
+	ds->ds_size = dbg->dbg_strtab_size;
+
+	/*
+	 * Inform application the creation of .debug_str ELF section.
+	 * Note that .debug_str use a different format than usual ELF
+	 * string table, so it should not have SHT_STRTAB as its type.
+	 */
+	ret = _dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error);
+
+	return (ret);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libdwarf/os.NetBSD.mk	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,2 @@
+# TODO(#511): Revert after the source tree is -Wconversion clean.
+WARNS=5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/Makefile	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,166 @@
+# $Id: Makefile 3594 2018-04-11 18:26:50Z jkoshy $
+
+TOP=	..
+
+LIB=	elf
+
+SRCS=	elf.c							\
+	elf_begin.c						\
+	elf_cntl.c						\
+	elf_end.c elf_errmsg.c elf_errno.c			\
+	elf_data.c						\
+	elf_fill.c						\
+	elf_flag.c						\
+	elf_getarhdr.c						\
+	elf_getarsym.c						\
+	elf_getbase.c						\
+	elf_getident.c						\
+	elf_hash.c						\
+	elf_kind.c						\
+	elf_memory.c						\
+	elf_next.c						\
+	elf_open.c						\
+	elf_rand.c						\
+	elf_rawfile.c						\
+	elf_phnum.c						\
+	elf_shnum.c						\
+	elf_shstrndx.c						\
+	elf_scn.c						\
+	elf_strptr.c						\
+	elf_update.c						\
+	elf_version.c						\
+	gelf_cap.c						\
+	gelf_checksum.c						\
+	gelf_dyn.c						\
+	gelf_ehdr.c						\
+	gelf_getclass.c						\
+	gelf_fsize.c						\
+	gelf_mips64el.c						\
+	gelf_move.c						\
+	gelf_phdr.c						\
+	gelf_rel.c						\
+	gelf_rela.c						\
+	gelf_shdr.c						\
+	gelf_sym.c						\
+	gelf_syminfo.c						\
+	gelf_symshndx.c						\
+	gelf_xlate.c						\
+	libelf_align.c						\
+	libelf_allocate.c					\
+	libelf_ar.c						\
+	libelf_ar_util.c					\
+	libelf_checksum.c					\
+	libelf_data.c						\
+	libelf_ehdr.c						\
+	libelf_extended.c					\
+	libelf_memory.c						\
+	libelf_open.c						\
+	libelf_phdr.c						\
+	libelf_shdr.c						\
+	libelf_xlate.c						\
+	${GENSRCS}
+
+INCS=		libelf.h gelf.h
+INCSDIR=	/usr/include
+
+GENSRCS=	libelf_fsize.c libelf_msize.c libelf_convert.c
+CLEANFILES=	${GENSRCS}
+
+SHLIB_MAJOR=	1
+
+WARNS?=	6
+
+MAN=	elf.3							\
+	elf_begin.3						\
+	elf_cntl.3						\
+	elf_end.3						\
+	elf_errmsg.3						\
+	elf_fill.3						\
+	elf_flagdata.3						\
+	elf_getarhdr.3						\
+	elf_getarsym.3						\
+	elf_getbase.3						\
+	elf_getdata.3						\
+	elf_getident.3						\
+	elf_getscn.3						\
+	elf_getphdrnum.3					\
+	elf_getphnum.3						\
+	elf_getshdrnum.3					\
+	elf_getshnum.3						\
+	elf_getshdrstrndx.3					\
+	elf_getshstrndx.3					\
+	elf_hash.3						\
+	elf_kind.3						\
+	elf_memory.3						\
+	elf_next.3						\
+	elf_open.3						\
+	elf_rawfile.3						\
+	elf_rand.3						\
+	elf_strptr.3						\
+	elf_update.3						\
+	elf_version.3						\
+	gelf.3							\
+	gelf_checksum.3						\
+	gelf_fsize.3						\
+	gelf_getcap.3						\
+	gelf_getclass.3						\
+	gelf_getdyn.3						\
+	gelf_getehdr.3						\
+	gelf_getmove.3						\
+	gelf_getphdr.3						\
+	gelf_getrel.3						\
+	gelf_getrela.3						\
+	gelf_getshdr.3						\
+	gelf_getsym.3						\
+	gelf_getsyminfo.3					\
+	gelf_getsymshndx.3					\
+	gelf_newehdr.3						\
+	gelf_newphdr.3						\
+	gelf_update_ehdr.3					\
+	gelf_xlatetof.3
+
+MLINKS+= \
+	elf_errmsg.3 elf_errno.3		\
+	elf_flagdata.3 elf_flagarhdr.3		\
+	elf_flagdata.3 elf_flagehdr.3		\
+	elf_flagdata.3 elf_flagelf.3		\
+	elf_flagdata.3 elf_flagphdr.3		\
+	elf_flagdata.3 elf_flagscn.3		\
+	elf_flagdata.3 elf_flagshdr.3		\
+	elf_getdata.3 elf_newdata.3		\
+	elf_getdata.3 elf_rawdata.3		\
+	elf_getscn.3 elf_ndxscn.3		\
+	elf_getscn.3 elf_newscn.3		\
+	elf_getscn.3 elf_nextscn.3		\
+	elf_getshstrndx.3 elf_setshstrndx.3	\
+	elf_open.3 elf_openmemory.3             \
+	gelf_getcap.3 gelf_update_cap.3		\
+	gelf_getdyn.3 gelf_update_dyn.3		\
+	gelf_getmove.3 gelf_update_move.3	\
+	gelf_getrel.3 gelf_update_rel.3		\
+	gelf_getrela.3 gelf_update_rela.3	\
+	gelf_getsym.3 gelf_update_sym.3		\
+	gelf_getsyminfo.3 gelf_update_syminfo.3	\
+	gelf_getsymshndx.3 gelf_update_symshndx.3 \
+	gelf_update_ehdr.3 gelf_update_phdr.3	\
+	gelf_update_ehdr.3 gelf_update_shdr.3	\
+	gelf_xlatetof.3 gelf_xlatetom.3
+
+.for E in 32 64
+MLINKS+= \
+	gelf_checksum.3	elf${E}_checksum.3 	\
+	gelf_fsize.3	elf${E}_fsize.3 	\
+	gelf_getehdr.3	elf${E}_getehdr.3	\
+	gelf_getphdr.3	elf${E}_getphdr.3	\
+	gelf_getshdr.3	elf${E}_getshdr.3	\
+	gelf_newehdr.3	elf${E}_newehdr.3	\
+	gelf_newphdr.3	elf${E}_newphdr.3	\
+	gelf_xlatetof.3	elf${E}_xlatetof.3	\
+	gelf_xlatetof.3	elf${E}_xlatetom.3
+.endfor
+
+libelf_convert.c:	elf_types.m4 libelf_convert.m4
+libelf_fsize.c:		elf_types.m4 libelf_fsize.m4
+libelf_msize.c:		elf_types.m4 libelf_msize.m4
+
+.include "${TOP}/mk/elftoolchain.lib.mk"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/Version.map	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,96 @@
+/* $Id: Version.map 2574 2012-09-11 15:11:59Z jkoshy $ */
+
+R1.0 {
+global:
+	elf32_checksum;
+	elf32_fsize;
+	elf32_getehdr;
+	elf32_getphdr;
+	elf32_getshdr;
+	elf32_newehdr;
+	elf32_newphdr;
+	elf32_xlatetof;
+	elf32_xlatetom;
+	elf64_checksum;
+	elf64_fsize;
+	elf64_getehdr;
+	elf64_getphdr;
+	elf64_getshdr;
+	elf64_newehdr;
+	elf64_newphdr;
+	elf64_xlatetof;
+	elf64_xlatetom;
+	elf_begin;
+	elf_cntl;
+	elf_end;
+	elf_errmsg;
+	elf_errno;
+	elf_fill;
+	elf_flagarhdr;
+	elf_flagdata;
+	elf_flagehdr;
+	elf_flagelf;
+	elf_flagphdr;
+	elf_flagscn;
+	elf_flagshdr;
+	elf_getarhdr;
+	elf_getarsym;
+	elf_getbase;
+	elf_getdata;
+	elf_getident;
+	elf_getphdrnum;
+	elf_getphnum;
+	elf_getscn;
+	elf_getshdrnum;
+	elf_getshdrstrndx;
+	elf_getshnum;
+	elf_getshstrndx;
+	elf_hash;
+	elf_kind;
+	elf_memory;
+	elf_ndxscn;
+	elf_newdata;
+	elf_newscn;
+	elf_next;
+	elf_nextscn;
+	elf_open;
+	elf_openmemory;
+	elf_rand;
+	elf_rawdata;
+	elf_rawfile;
+	elf_setshstrndx;
+	elf_strptr;
+	elf_update;
+	elf_version;
+	gelf_checksum;
+	gelf_fsize;
+	gelf_getcap;
+	gelf_getclass;
+	gelf_getdyn;
+	gelf_getehdr;
+	gelf_getmove;
+	gelf_getphdr;
+	gelf_getrel;
+	gelf_getrela;
+	gelf_getshdr;
+	gelf_getsym;
+	gelf_getsyminfo;
+	gelf_getsymshndx;
+	gelf_newehdr;
+	gelf_newphdr;
+	gelf_update_cap;
+	gelf_update_dyn;
+	gelf_update_ehdr;
+	gelf_update_move;
+	gelf_update_phdr;
+	gelf_update_rel;
+	gelf_update_rela;
+	gelf_update_shdr;
+	gelf_update_sym;
+	gelf_update_syminfo;
+	gelf_update_symshndx;
+	gelf_xlatetof;
+	gelf_xlatetom;
+local:
+	*;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/_libelf.h	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,242 @@
+/*-
+ * Copyright (c) 2006,2008-2011 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: _libelf.h 3174 2015-03-27 17:13:41Z emaste $
+ */
+
+#ifndef	__LIBELF_H_
+#define	__LIBELF_H_
+
+#include <sys/queue.h>
+
+#include "_libelf_config.h"
+
+#include "_elftc.h"
+
+/*
+ * Library-private data structures.
+ */
+
+#define LIBELF_MSG_SIZE	256
+
+struct _libelf_globals {
+	int		libelf_arch;
+	unsigned int	libelf_byteorder;
+	int		libelf_class;
+	int		libelf_error;
+	int		libelf_fillchar;
+	unsigned int	libelf_version;
+	unsigned char	libelf_msg[LIBELF_MSG_SIZE];
+};
+
+extern struct _libelf_globals _libelf;
+
+#define	LIBELF_PRIVATE(N)	(_libelf.libelf_##N)
+
+#define	LIBELF_ELF_ERROR_MASK			0xFF
+#define	LIBELF_OS_ERROR_SHIFT			8
+
+#define	LIBELF_ERROR(E, O) (((E) & LIBELF_ELF_ERROR_MASK) |	\
+	((O) << LIBELF_OS_ERROR_SHIFT))
+
+#define	LIBELF_SET_ERROR(E, O) do {					\
+		LIBELF_PRIVATE(error) = LIBELF_ERROR(ELF_E_##E, (O));	\
+	} while (0)
+
+#define	LIBELF_ADJUST_AR_SIZE(S)	(((S) + 1U) & ~1U)
+
+/*
+ * Flags for library internal use.  These use the upper 16 bits of the
+ * `e_flags' field.
+ */
+#define	LIBELF_F_API_MASK	0x00FFFFU  /* Flags defined by the API. */
+#define	LIBELF_F_AR_HEADER	0x010000U  /* translated header available */
+#define	LIBELF_F_AR_VARIANT_SVR4 0x020000U /* BSD style ar(1) archive */
+#define	LIBELF_F_DATA_MALLOCED	0x040000U /* whether data was malloc'ed */
+#define	LIBELF_F_RAWFILE_MALLOC	0x080000U /* whether e_rawfile was malloc'ed */
+#define	LIBELF_F_RAWFILE_MMAP	0x100000U /* whether e_rawfile was mmap'ed */
+#define	LIBELF_F_SHDRS_LOADED	0x200000U /* whether all shdrs were read in */
+#define	LIBELF_F_SPECIAL_FILE	0x400000U /* non-regular file */
+
+struct _Elf {
+	int		e_activations;	/* activation count */
+	unsigned int	e_byteorder;	/* ELFDATA* */
+	int		e_class;	/* ELFCLASS*  */
+	Elf_Cmd		e_cmd;		/* ELF_C_* used at creation time */
+	int		e_fd;		/* associated file descriptor */
+	unsigned int	e_flags;	/* ELF_F_* & LIBELF_F_* flags */
+	Elf_Kind	e_kind;		/* ELF_K_* */
+	Elf		*e_parent; 	/* non-NULL for archive members */
+	unsigned char	*e_rawfile;	/* uninterpreted bytes */
+	size_t		e_rawsize;	/* size of uninterpreted bytes */
+	unsigned int	e_version;	/* file version */
+
+	/*
+	 * Header information for archive members.  See the
+	 * LIBELF_F_AR_HEADER flag.
+	 */
+	union {
+		Elf_Arhdr	*e_arhdr;	/* translated header */
+		unsigned char	*e_rawhdr;	/* untranslated header */
+	} e_hdr;
+
+	union {
+		struct {		/* ar(1) archives */
+			off_t	e_next;	/* set by elf_rand()/elf_next() */
+			int	e_nchildren;
+			unsigned char *e_rawstrtab; /* file name strings */
+			size_t	e_rawstrtabsz;
+			unsigned char *e_rawsymtab;	/* symbol table */
+			size_t	e_rawsymtabsz;
+			Elf_Arsym *e_symtab;
+			size_t	e_symtabsz;
+		} e_ar;
+		struct {		/* regular ELF files */
+			union {
+				Elf32_Ehdr *e_ehdr32;
+				Elf64_Ehdr *e_ehdr64;
+			} e_ehdr;
+			union {
+				Elf32_Phdr *e_phdr32;
+				Elf64_Phdr *e_phdr64;
+			} e_phdr;
+			STAILQ_HEAD(, _Elf_Scn)	e_scn;	/* section list */
+			size_t	e_nphdr;	/* number of Phdr entries */
+			size_t	e_nscn;		/* number of sections */
+			size_t	e_strndx;	/* string table section index */
+		} e_elf;
+	} e_u;
+};
+
+/*
+ * The internal descriptor wrapping the "Elf_Data" type.
+ */
+struct _Libelf_Data {
+	Elf_Data	d_data;		/* The exported descriptor. */
+	Elf_Scn		*d_scn;		/* The containing section */
+	unsigned int	d_flags;
+	STAILQ_ENTRY(_Libelf_Data) d_next;
+};
+
+struct _Elf_Scn {
+	union {
+		Elf32_Shdr	s_shdr32;
+		Elf64_Shdr	s_shdr64;
+	} s_shdr;
+	STAILQ_HEAD(, _Libelf_Data) s_data;	/* translated data */
+	STAILQ_HEAD(, _Libelf_Data) s_rawdata;	/* raw data */
+	STAILQ_ENTRY(_Elf_Scn) s_next;
+	struct _Elf	*s_elf;		/* parent ELF descriptor */
+	unsigned int	s_flags;	/* flags for the section as a whole */
+	size_t		s_ndx;		/* index# for this section */
+	uint64_t	s_offset;	/* managed by elf_update() */
+	uint64_t	s_rawoff;	/* original offset in the file */
+	uint64_t	s_size;		/* managed by elf_update() */
+};
+
+
+enum {
+	ELF_TOFILE,
+	ELF_TOMEMORY
+};
+
+
+/*
+ * The LIBELF_COPY macros are used to copy fields from a GElf_*
+ * structure to their 32-bit counterparts, while checking for out of
+ * range values.
+ *
+ * - LIBELF_COPY_U32 :: copy an unsigned 32 bit field.
+ * - LIBELF_COPY_S32 :: copy a signed 32 bit field.
+ */
+
+#define	LIBELF_COPY_U32(DST, SRC, NAME)	do {			\
+		if ((SRC)->NAME > UINT32_MAX) {			\
+			LIBELF_SET_ERROR(RANGE, 0);		\
+			return (0);				\
+		}						\
+		(DST)->NAME = (SRC)->NAME & 0xFFFFFFFFU;	\
+	} while (0)
+
+#define	LIBELF_COPY_S32(DST, SRC, NAME)	do {			\
+		if ((SRC)->NAME > INT32_MAX ||			\
+		    (SRC)->NAME < INT32_MIN) {			\
+			LIBELF_SET_ERROR(RANGE, 0);		\
+			return (0);				\
+		}						\
+		(DST)->NAME = (int32_t) (SRC)->NAME;		\
+	} while (0)
+
+
+/*
+ * Function Prototypes.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+struct _Libelf_Data *_libelf_allocate_data(Elf_Scn *_s);
+Elf	*_libelf_allocate_elf(void);
+Elf_Scn	*_libelf_allocate_scn(Elf *_e, size_t _ndx);
+Elf_Arhdr *_libelf_ar_gethdr(Elf *_e);
+Elf	*_libelf_ar_open(Elf *_e, int _reporterror);
+Elf	*_libelf_ar_open_member(int _fd, Elf_Cmd _c, Elf *_ar);
+Elf_Arsym *_libelf_ar_process_bsd_symtab(Elf *_ar, size_t *_dst);
+Elf_Arsym *_libelf_ar_process_svr4_symtab(Elf *_ar, size_t *_dst);
+long	 _libelf_checksum(Elf *_e, int _elfclass);
+void	*_libelf_ehdr(Elf *_e, int _elfclass, int _allocate);
+unsigned int _libelf_falign(Elf_Type _t, int _elfclass);
+size_t	_libelf_fsize(Elf_Type _t, int _elfclass, unsigned int _version,
+    size_t count);
+int	(*_libelf_get_translator(Elf_Type _t, int _direction, int _elfclass))
+	    (unsigned char *_dst, size_t dsz, unsigned char *_src,
+	     size_t _cnt, int _byteswap);
+void	*_libelf_getphdr(Elf *_e, int _elfclass);
+void	*_libelf_getshdr(Elf_Scn *_scn, int _elfclass);
+void	_libelf_init_elf(Elf *_e, Elf_Kind _kind);
+int	_libelf_is_mips64el(Elf *e);
+int	_libelf_load_section_headers(Elf *e, void *ehdr);
+unsigned int _libelf_malign(Elf_Type _t, int _elfclass);
+Elf	*_libelf_memory(unsigned char *_image, size_t _sz, int _reporterror);
+size_t	_libelf_msize(Elf_Type _t, int _elfclass, unsigned int _version);
+void	*_libelf_newphdr(Elf *_e, int _elfclass, size_t _count);
+Elf	*_libelf_open_object(int _fd, Elf_Cmd _c, int _reporterror);
+Elf64_Xword _libelf_mips64el_r_info_tof(Elf64_Xword r_info);
+Elf64_Xword _libelf_mips64el_r_info_tom(Elf64_Xword r_info);
+struct _Libelf_Data *_libelf_release_data(struct _Libelf_Data *_d);
+Elf	*_libelf_release_elf(Elf *_e);
+Elf_Scn	*_libelf_release_scn(Elf_Scn *_s);
+int	_libelf_setphnum(Elf *_e, void *_eh, int _elfclass, size_t _phnum);
+int	_libelf_setshnum(Elf *_e, void *_eh, int _elfclass, size_t _shnum);
+int	_libelf_setshstrndx(Elf *_e, void *_eh, int _elfclass,
+    size_t _shstrndx);
+Elf_Data *_libelf_xlate(Elf_Data *_d, const Elf_Data *_s,
+    unsigned int _encoding, int _elfclass, int _direction);
+int	_libelf_xlate_shtype(uint32_t _sht);
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* __LIBELF_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/_libelf_ar.h	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 2010 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS `AS IS' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: _libelf_ar.h 3013 2014-03-23 06:16:59Z jkoshy $
+ */
+
+#ifndef	__LIBELF_AR_H_
+#define	__LIBELF_AR_H_
+
+/*
+ * Prototypes and declarations needed by libelf's ar(1) archive
+ * handling code.
+ */
+
+#include <ar.h>
+
+#define	LIBELF_AR_BSD_EXTENDED_NAME_PREFIX	"#1/"
+#define	LIBELF_AR_BSD_SYMTAB_NAME		"__.SYMDEF"
+#define	LIBELF_AR_BSD_EXTENDED_NAME_PREFIX_SIZE	\
+	(sizeof(LIBELF_AR_BSD_EXTENDED_NAME_PREFIX) - 1)
+
+#define	IS_EXTENDED_BSD_NAME(NAME)				\
+	(strncmp((const char *) (NAME),				\
+	 LIBELF_AR_BSD_EXTENDED_NAME_PREFIX,			\
+	 LIBELF_AR_BSD_EXTENDED_NAME_PREFIX_SIZE) == 0)
+
+
+unsigned char *_libelf_ar_get_string(const char *_buf, size_t _sz,
+    unsigned int _rawname, int _svr4names);
+char	*_libelf_ar_get_raw_name(const struct ar_hdr *_arh);
+char	*_libelf_ar_get_translated_name(const struct ar_hdr *_arh, Elf *_ar);
+int	_libelf_ar_get_number(const char *_buf, size_t _sz,
+    unsigned int _base, size_t *_ret);
+
+#endif	/* __LIBELF_AR_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/_libelf_config.h	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,189 @@
+/*-
+ * Copyright (c) 2008-2011 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: _libelf_config.h 3566 2017-08-31 02:28:40Z emaste $
+ */
+
+#if defined(__APPLE__) || defined(__DragonFly__)
+
+#if	defined(__amd64__)
+#define	LIBELF_ARCH		EM_X86_64
+#define	LIBELF_BYTEORDER	ELFDATA2LSB
+#define	LIBELF_CLASS		ELFCLASS64
+#elif	defined(__i386__)
+#define	LIBELF_ARCH		EM_386
+#define	LIBELF_BYTEORDER	ELFDATA2LSB
+#define	LIBELF_CLASS		ELFCLASS32
+#endif
+
+#endif	/* __DragonFly__ */
+
+#ifdef __FreeBSD__
+
+/*
+ * Define LIBELF_{ARCH,BYTEORDER,CLASS} based on the machine architecture.
+ * See also: <machine/elf.h>.
+ */
+
+#if	defined(__amd64__)
+
+#define	LIBELF_ARCH		EM_X86_64
+#define	LIBELF_BYTEORDER	ELFDATA2LSB
+#define	LIBELF_CLASS		ELFCLASS64
+
+#elif	defined(__aarch64__)
+
+#define	LIBELF_ARCH		EM_AARCH64
+#define	LIBELF_BYTEORDER	ELFDATA2LSB
+#define	LIBELF_CLASS		ELFCLASS64
+
+#elif	defined(__arm__)
+
+#define	LIBELF_ARCH		EM_ARM
+#if	defined(__ARMEB__)	/* Big-endian ARM. */
+#define	LIBELF_BYTEORDER	ELFDATA2MSB
+#else
+#define	LIBELF_BYTEORDER	ELFDATA2LSB
+#endif
+#define	LIBELF_CLASS		ELFCLASS32
+
+#elif	defined(__i386__)
+
+#define	LIBELF_ARCH		EM_386
+#define	LIBELF_BYTEORDER	ELFDATA2LSB
+#define	LIBELF_CLASS		ELFCLASS32
+
+#elif	defined(__ia64__)
+
+#define	LIBELF_ARCH		EM_IA_64
+#define	LIBELF_BYTEORDER	ELFDATA2LSB
+#define	LIBELF_CLASS		ELFCLASS64
+
+#elif	defined(__mips__)
+
+#define	LIBELF_ARCH		EM_MIPS
+#if	defined(__MIPSEB__)
+#define	LIBELF_BYTEORDER	ELFDATA2MSB
+#else
+#define	LIBELF_BYTEORDER	ELFDATA2LSB
+#endif
+#define	LIBELF_CLASS		ELFCLASS32
+
+#elif	defined(__powerpc__)
+
+#define	LIBELF_ARCH		EM_PPC
+#define	LIBELF_BYTEORDER	ELFDATA2MSB
+#define	LIBELF_CLASS		ELFCLASS32
+
+#elif	defined(__riscv) && (__riscv_xlen == 64)
+
+#define	LIBELF_ARCH		EM_RISCV
+#define	LIBELF_BYTEORDER	ELFDATA2LSB
+#define	LIBELF_CLASS		ELFCLASS64
+
+#elif	defined(__sparc__)
+
+#define	LIBELF_ARCH		EM_SPARCV9
+#define	LIBELF_BYTEORDER	ELFDATA2MSB
+#define	LIBELF_CLASS		ELFCLASS64
+
+#else
+#error	Unknown FreeBSD architecture.
+#endif
+#endif  /* __FreeBSD__ */
+
+/*
+ * Definitions for Minix3.
+ */
+#ifdef __minix
+
+#define	LIBELF_ARCH		EM_386
+#define	LIBELF_BYTEORDER	ELFDATA2LSB
+#define	LIBELF_CLASS		ELFCLASS32
+
+#endif	/* __minix */
+
+#ifdef __NetBSD__
+
+#include <machine/elf_machdep.h>
+
+#if	!defined(ARCH_ELFSIZE)
+#error	ARCH_ELFSIZE is not defined.
+#endif
+
+#if	ARCH_ELFSIZE == 32
+#define	LIBELF_ARCH		ELF32_MACHDEP_ID
+#define	LIBELF_BYTEORDER	ELF32_MACHDEP_ENDIANNESS
+#define	LIBELF_CLASS		ELFCLASS32
+#define	Elf_Note		Elf32_Nhdr
+#else
+#define	LIBELF_ARCH		ELF64_MACHDEP_ID
+#define	LIBELF_BYTEORDER	ELF64_MACHDEP_ENDIANNESS
+#define	LIBELF_CLASS		ELFCLASS64
+#define	Elf_Note		Elf64_Nhdr
+#endif
+
+#endif	/* __NetBSD__ */
+
+#if defined(__OpenBSD__)
+
+#include <machine/exec.h>
+
+#define	LIBELF_ARCH		ELF_TARG_MACH
+#define	LIBELF_BYTEORDER	ELF_TARG_DATA
+#define	LIBELF_CLASS		ELF_TARG_CLASS
+
+#endif
+
+/*
+ * GNU & Linux compatibility.
+ *
+ * `__linux__' is defined in an environment runs the Linux kernel and glibc.
+ * `__GNU__' is defined in an environment runs a GNU kernel (Hurd) and glibc.
+ * `__GLIBC__' is defined for an environment that runs glibc over a non-GNU
+ *     kernel such as GNU/kFreeBSD.
+ */
+
+#if defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)
+
+#if defined(__linux__)
+
+#include "native-elf-format.h"
+
+#define	LIBELF_CLASS		ELFTC_CLASS
+#define	LIBELF_ARCH		ELFTC_ARCH
+#define	LIBELF_BYTEORDER	ELFTC_BYTEORDER
+
+#endif	/* defined(__linux__) */
+
+#if	LIBELF_CLASS == ELFCLASS32
+#define	Elf_Note		Elf32_Nhdr
+#elif   LIBELF_CLASS == ELFCLASS64
+#define	Elf_Note		Elf64_Nhdr
+#else
+#error  LIBELF_CLASS needs to be one of ELFCLASS32 or ELFCLASS64
+#endif
+
+#endif /* defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,611 @@
+.\" Copyright (c) 2006-2008,2011 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf.3 3195 2015-05-12 17:22:19Z emaste $
+.\"
+.Dd July 28, 2014
+.Os
+.Dt ELF 3
+.Sh NAME
+.Nm elf
+.Nd API for manipulating ELF objects
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Sh DESCRIPTION
+The
+.Lb libelf
+provides functions that allow an application to read and manipulate
+ELF object files, and to read
+.Xr ar 1
+archives.
+The library allows the manipulation of ELF objects in a byte ordering
+and word-size independent way, allowing an application to read and
+create ELF objects for 32 and 64 bit architectures and for little-
+and big-endian machines.
+The library is capable of processing ELF objects that use extended
+section numbering.
+.Pp
+This manual page serves to provide an overview of the functionality in
+the ELF library.
+Further information may found in the manual pages for individual
+.Xr ELF 3
+functions that comprise the library.
+.Ss ELF Concepts
+As described in
+.Xr elf 5 ,
+ELF files contain several data structures that are laid out in a
+specific way.
+ELF files begin with an
+.Dq Executable Header ,
+and may contain an optional
+.Dq Program Header Table ,
+and optional data in the form of ELF
+.Dq sections .
+A
+.Dq Section Header Table
+describes the content of the data in these sections.
+.Pp
+ELF objects have an associated
+.Dq "ELF class"
+which denotes the natural machine word size for the architecture
+the object is associated with.
+Objects for 32 bit architectures have an ELF class of
+.Dv ELFCLASS32 .
+Objects for 64 bit architectures have an ELF class of
+.Dv ELFCLASS64 .
+.Pp
+ELF objects also have an associated
+.Dq endianness
+which denotes the endianness of the machine architecture associated
+with the object.
+This may be
+.Dv ELFDATA2LSB
+for little-endian architectures and
+.Dv ELFDATA2MSB
+for big-endian architectures.
+.Pp
+ELF objects are also associated with an API version number.
+This version number determines the layout of the individual components
+of an ELF file and the semantics associated with these.
+.Ss Data Representation And Translation
+The
+.Xr ELF 3
+library distinguishes between
+.Dq native
+representations of ELF data structures and their
+.Dq file
+representations.
+.Pp
+An application would work with ELF data in its
+.Dq native
+representation, i.e., using the native byteorder and alignment mandated
+by the processor the application is running on.
+The
+.Dq file
+representation of the same data could use a different byte ordering
+and follow different constraints on object alignment than these native
+constraints.
+.Pp
+Accordingly, the
+.Xr ELF 3
+library offers translation facilities
+.Xr ( elf32_xlatetof 3 ,
+.Xr elf32_xlatetom 3 ,
+.Xr elf64_xlatetof 3
+and
+.Xr elf64_xlatetom 3 )
+to and from these
+representations and also provides higher-level APIs that retrieve and store
+data from the ELF object in a transparent manner.
+.Ss Library Working Version
+Conceptually, there are three version numbers associated with an
+application using the ELF library to manipulate ELF objects:
+.Bl -bullet -compact -offset indent
+.It
+The ELF version that the application was compiled against.
+This version determines the ABI expected by the application.
+.It
+The ELF version of the ELF object being manipulated by the
+application through the ELF library.
+.It
+The ELF version (or set of versions) supported by the ELF library itself.
+.El
+.Pp
+In order to facilitate working with ELF objects of differing versions,
+the ELF library requires the application to call the
+.Fn elf_version
+function before invoking many of its operations, in order to inform
+the library of the application's desired working version.
+.Pp
+In the current implementation, all three versions have to be
+.Dv EV_CURRENT .
+.Ss Namespace use
+The ELF library uses the following prefixes:
+.Bl -tag -width "ELF_F_*"
+.It Dv elf_
+Used for class-independent functions.
+.It Dv elf32_
+Used for functions working with 32 bit ELF objects.
+.It Dv elf64_
+Used for functions working with 64 bit ELF objects.
+.It Dv Elf_
+Used for class-independent data types.
+.It Dv ELF_C_
+Used for command values used in a few functions.
+These symbols are defined as members of the
+.Vt Dv Elf_Cmd
+enumeration.
+.It Dv ELF_E_
+Used for error numbers.
+.It Dv ELF_F_
+Used for flags.
+.It Dv ELF_K_
+These constants define the kind of file associated with an ELF
+descriptor.
+See
+.Xr elf_kind 3 .
+The symbols are defined by the
+.Vt Elf_Kind
+enumeration.
+.It Dv ELF_T_
+These values are defined by the
+.Vt Elf_Type
+enumeration, and denote the types of ELF data structures
+that can be present in an ELF object.
+.El
+.Pp
+In addition, the library uses symbols with prefixes
+.Dv _ELF
+and
+.Dv _libelf
+for its internal use.
+.Ss Descriptors
+Applications communicate with the library using descriptors.
+These are:
+.Bl -tag -width ".Vt Elf_Data"
+.It Vt Elf
+An
+.Vt Elf
+descriptor represents an ELF object or an
+.Xr ar 1
+archive.
+It is allocated using one of the
+.Fn elf_begin
+or
+.Fn elf_memory
+functions.
+An
+.Vt Elf
+descriptor can be used to read and write data to an ELF file.
+An
+.Vt Elf
+descriptor can be associated with zero or more
+.Vt Elf_Scn
+section descriptors.
+.Pp
+Given an ELF descriptor, the application may retrieve the ELF
+object's class-dependent
+.Dq "Executable Header"
+structures using the
+.Fn elf32_getehdr
+or
+.Fn elf64_getehdr
+functions.
+A new Ehdr structure may be allocated using the
+.Fn elf64_newehdr
+or
+.Fn elf64_newehdr
+functions.
+.Pp
+The
+.Dq "Program Header Table"
+associated with an ELF descriptor may be allocated using the
+.Fn elf32_getphdr
+or
+.Fn elf64_getphdr
+functions.
+A new program header table may be allocated or an existing table
+resized using the
+.Fn elf32_newphdr
+or
+.Fn elf64_newphdr
+functions.
+.Pp
+The
+.Vt Elf
+structure is opaque and has no members visible to the
+application.
+.\" TODO describe the Elf_Arhdr and Elf_Arsym structures.
+.It Vt Elf_Data
+An
+.Vt Elf_Data
+data structure describes an individual chunk of a ELF file as
+represented in memory.
+It has the following application-visible members:
+.Bl -tag -width ".Vt unsigned int d_version" -compact
+.It Vt "uint64_t d_align"
+The in-file alignment of the data buffer within its containing ELF section.
+This value must be non-zero and a power of two.
+.It Vt "void *d_buf"
+A pointer to data in memory.
+.It Vt "uint64_t d_off"
+The offset within the containing section where this descriptor's data
+would be placed.
+This field will be computed by the library unless the application
+requests full control of the ELF object's layout.
+.It Vt "uint64_t d_size"
+The number of bytes of data in this descriptor.
+.It Vt "Elf_Type d_type"
+The ELF type (see below) of the data in this descriptor.
+.It Vt "unsigned int d_version"
+The operating version for the data in this buffer.
+.El
+.Pp
+.Vt Elf_Data
+descriptors are usually associated with
+.Vt Elf_Scn
+descriptors.
+Existing data descriptors associated with an ELF section may be
+structures are retrieved using the
+.Fn elf_getdata
+and
+.Fn elf_rawdata
+functions.
+The
+.Fn elf_newdata
+function may be used to attach new data descriptors to an ELF section.
+.It Vt Elf_Scn
+.Vt Elf_Scn
+descriptors represent a section in an ELF object.
+.Pp
+They are retrieved using the
+.Fn elf_getscn
+function.
+An application may iterate through the existing sections of an ELF
+object using the
+.Fn elf_nextscn
+function.
+New sections may be allocated using the
+.Fn elf_newscn
+function.
+.Pp
+The
+.Vt Elf_Scn
+descriptor is opaque and contains no application modifiable fields.
+.El
+.Ss Supported Elf Types
+The following ELF datatypes are supported by the library.
+.Pp
+.Bl -tag -width ".Dv ELF_T_SYMINFO" -compact
+.It Dv ELF_T_ADDR
+Machine addresses.
+.It Dv ELF_T_BYTE
+Byte data.
+The library will not attempt to translate byte data.
+.It Dv ELF_T_CAP
+Software and hardware capability records.
+.It Dv ELF_T_DYN
+Records used in a section of type
+.Dv SHT_DYNAMIC .
+.It Dv ELF_T_EHDR
+ELF executable header.
+.It Dv ELF_T_GNUHASH
+GNU-style hash tables.
+.It Dv ELF_T_HALF
+16-bit unsigned words.
+.It Dv ELF_T_LWORD
+64 bit unsigned words.
+.It Dv ELF_T_MOVE
+ELF Move records.
+.\".It Dv ELF_T_MOVEP
+.\" As yet unsupported.
+.It Dv ELF_T_NOTE
+ELF Note structures.
+.It Dv ELF_T_OFF
+File offsets.
+.It Dv ELF_T_PHDR
+ELF program header table entries.
+.It Dv ELF_T_REL
+ELF relocation entries.
+.It Dv ELF_T_RELA
+ELF relocation entries with addends.
+.It Dv ELF_T_SHDR
+ELF section header entries.
+.It Dv ELF_T_SWORD
+Signed 32-bit words.
+.It Dv ELF_T_SXWORD
+Signed 64-bit words.
+.It Dv ELF_T_SYMINFO
+ELF symbol information.
+.It Dv ELF_T_SYM
+ELF symbol table entries.
+.It Dv ELF_T_VDEF
+Symbol version definition records.
+.It Dv ELF_T_VNEED
+Symbol version requirement records.
+.It Dv ELF_T_WORD
+Unsigned 32-bit words.
+.It Dv ELF_T_XWORD
+Unsigned 64-bit words.
+.El
+.Pp
+The symbol
+.Dv ELF_T_NUM
+denotes the number of Elf types known to the library.
+.Pp
+The following table shows the mapping between ELF section types
+defined in
+.Xr elf 5
+and the types supported by the library.
+.Bl -column ".Dv SHT_PREINIT_ARRAY" ".Dv ELF_T_SYMINFO"
+.It Em Section Type Ta Em "Library Type" Ta Em Description
+.It Dv SHT_DYNAMIC Ta Dv ELF_T_DYN Ta Xo
+.Sq .dynamic
+section entries.
+.Xc
+.It Dv SHT_DYNSYM Ta Dv ELF_T_SYM Ta Symbols for dynamic linking.
+.It Dv SHT_FINI_ARRAY Ta Dv ELF_T_ADDR Ta Termination function pointers.
+.It Dv SHT_GNU_HASH Ta Dv ELF_T_GNUHASH Ta GNU hash sections.
+.It Dv SHT_GNU_LIBLIST Ta Dv ELF_T_WORD Ta List of libraries to be pre-linked.
+.It Dv SHT_GNU_verdef Ta Dv ELF_T_VDEF Ta Symbol version definitions.
+.It Dv SHT_GNU_verneed Ta Dv ELF_T_VNEED Ta Symbol versioning requirements.
+.It Dv SHT_GNU_versym Ta Dv ELF_T_HALF Ta Version symbols.
+.It Dv SHT_GROUP Ta Dv ELF_T_WORD Ta Section group marker.
+.It Dv SHT_HASH Ta Dv ELF_T_HASH Ta Symbol hashes.
+.It Dv SHT_INIT_ARRAY Ta Dv ELF_T_ADDR Ta Initialization function pointers.
+.It Dv SHT_NOBITS Ta Dv ELF_T_BYTE Ta Xo
+Empty sections.
+See
+.Xr elf 5 .
+.Xc
+.It Dv SHT_NOTE Ta Dv ELF_T_NOTE Ta ELF note records.
+.It Dv SHT_PREINIT_ARRAY Ta Dv ELF_T_ADDR Ta Pre-initialization function pointers.
+.It Dv SHT_PROGBITS Ta Dv ELF_T_BYTE Ta Machine code.
+.It Dv SHT_REL Ta Dv ELF_T_REL Ta ELF relocation records.
+.It Dv SHT_RELA Ta Dv ELF_T_RELA Ta Relocation records with addends.
+.It Dv SHT_STRTAB Ta Dv ELF_T_BYTE Ta String tables.
+.It Dv SHT_SYMTAB Ta Dv ELF_T_SYM Ta Symbol tables.
+.It Dv SHT_SYMTAB_SHNDX Ta Dv ELF_T_WORD Ta Used with extended section numbering.
+.It Dv SHT_SUNW_dof Ta Dv ELF_T_BYTE Ta Xo
+Used by
+.Xr dtrace 1 .
+.Xc
+.It Dv SHT_SUNW_move Ta Dv ELF_T_MOVE Ta ELF move records.
+.It Dv SHT_SUNW_syminfo Ta Dv ELF_T_SYMINFO Ta Additional symbol flags.
+.It Dv SHT_SUNW_verdef Ta Dv ELF_T_VDEF Ta Xo
+Same as
+.Dv SHT_GNU_verdef .
+.Xc
+.It Dv SHT_SUNW_verneed Ta Dv ELF_T_VNEED Ta Xo
+Same as
+.Dv SHT_GNU_verneed .
+.Xc
+.It Dv SHT_SUNW_versym Ta Dv ELF_T_HALF Ta Xo
+Same as
+.Dv SHT_GNU_versym .
+.Xc
+.El
+.Pp
+Section types in the range
+.Ns [ Dv SHT_LOOS ,
+.Dv SHT_HIUSER ]
+are otherwise considered to be of type
+.Dv ELF_T_BYTE .
+.Ss Functional Grouping
+This section contains a brief overview of the available functionality
+in the ELF library.
+Each function listed here is described further in its own manual page.
+.Bl -tag -width indent
+.It "Archive Access"
+.Bl -tag -compact
+.It Fn elf_getarsym
+Retrieve the archive symbol table.
+.It Fn elf_getarhdr
+Retrieve the archive header for an object.
+.It Fn elf_getbase
+Retrieve the offset of a member inside an archive.
+.It Fn elf_next
+Iterate through an
+.Xr ar 1
+archive.
+.It Fn elf_rand
+Random access inside an
+.Xr ar 1
+archive.
+.El
+.It "Data Structures"
+.Bl -tag -compact
+.It Fn elf_getdata
+Retrieve translated data for an ELF section.
+.It Fn elf_getscn
+Retrieve the section descriptor for a named section.
+.It Fn elf_ndxscn
+Retrieve the index for a section.
+.It Fn elf_newdata
+Add a new
+.Vt Elf_Data
+descriptor to an ELF section.
+.It Fn elf_newscn
+Add a new section descriptor to an ELF descriptor.
+.It Fn elf_nextscn
+Iterate through the sections in an ELF object.
+.It Fn elf_rawdata
+Retrieve untranslated data for an ELF section.
+.It Fn elf_rawfile
+Return a pointer to the untranslated file contents for an ELF object.
+.It Fn elf32_getehdr , Fn elf64_getehdr
+Retrieve the Executable Header in an ELF object.
+.It Fn elf32_getphdr , Fn elf64_getphdr
+Retrieve the Program Header Table in an ELF object.
+.It Fn elf32_getshdr , Fn elf64_getshdr
+Retrieve the ELF section header associated with an
+.Vt Elf_Scn
+descriptor.
+.It Fn elf32_newehdr , Fn elf64_newehdr
+Allocate an Executable Header in an ELF object.
+.It Fn elf32_newphdr , Fn elf64_newphdr
+Allocate or resize the Program Header Table in an ELF object.
+.El
+.It "Data Translation"
+.Bl -tag -compact
+.It Fn elf32_xlatetof , Fn elf64_xlatetof
+Translate an ELF data structure from its native representation to its
+file representation.
+.It Fn elf32_xlatetom , Fn elf64_xlatetom
+Translate an ELF data structure from its file representation to a
+native representation.
+.El
+.It "Error Reporting"
+.Bl -tag -compact
+.It Fn elf_errno
+Retrieve the current error.
+.It Fn elf_errmsg
+Retrieve a human readable description of the current error.
+.El
+.It "Initialization"
+.Bl -tag -compact
+.It Fn elf_begin
+Opens an
+.Xr ar 1
+archive or ELF object given a file descriptor.
+.It Fn elf_end
+Close an ELF descriptor and release all its resources.
+.It Fn elf_memory
+Opens an
+.Xr ar 1
+archive or ELF object present in a memory arena.
+.It Fn elf_version
+Sets the operating version.
+.El
+.It "IO Control"
+.Bl -tag -width ".Fn elf_setshstrndx" -compact
+.It Fn elf_cntl
+Manage the association between and ELF descriptor and its underlying file.
+.It Fn elf_flagdata
+Mark an
+.Vt Elf_Data
+descriptor as dirty.
+.It Fn elf_flagehdr
+Mark the ELF Executable Header in an ELF descriptor as dirty.
+.It Fn elf_flagphdr
+Mark the ELF Program Header Table in an ELF descriptor as dirty.
+.It Fn elf_flagscn
+Mark an
+.Vt Elf_Scn
+descriptor as dirty.
+.It Fn elf_flagshdr
+Mark an ELF Section Header as dirty.
+.It Fn elf_setshstrndx
+Set the index of the section name string table for the ELF object.
+.It Fn elf_update
+Recompute ELF object layout and optionally write the modified object
+back to the underlying file.
+.El
+.It "Queries"
+.Bl -tag -width ".Fn elf_getshstrndx" -compact
+.It Fn elf32_checksum , Fn elf64_checkum
+Compute checksum of an ELF object.
+.It Fn elf_getident
+Retrieve the identification bytes for an ELF object.
+.It Fn elf_getshnum
+Retrieve the number of sections in an ELF object.
+.It Fn elf_getshstrndx
+Retrieve the section index of the section name string table in
+an ELF object.
+.It Fn elf_hash
+Compute the ELF hash value of a string.
+.It Fn elf_kind
+Query the kind of object associated with an ELF descriptor.
+.It Fn elf32_fsize , Fn elf64_fsize
+Return the size of the file representation of an ELF type.
+.El
+.El
+.Ss Controlling ELF Object Layout
+In the usual mode of operation, library will compute section
+offsets and alignments based on the contents of an ELF descriptor's
+sections without need for further intervention by the
+application.
+.Pp
+However, if the application wishes to take complete charge of the
+layout of the ELF file, it may set the
+.Dv ELF_F_LAYOUT
+flag on an ELF descriptor using
+.Xr elf_flagelf 3 ,
+following which the library will use the data offsets and alignments
+specified by the application when laying out the file.
+Application control of file layout is described further in the
+.Xr elf_update 3
+manual page.
+.Pp
+Gaps in between sections will be filled with the fill character
+set by function
+.Fn elf_fill .
+.Ss Error Handling
+In case an error is encountered, these library functions set an
+internal error number and signal the presence of the error by
+returning an special return value.
+The application can check the
+current error number by calling
+.Xr elf_errno 3 .
+A human readable description of the recorded error is available by
+calling
+.Xr elf_errmsg 3 .
+.Ss Memory Management Rules
+The library keeps track of all
+.Vt Elf_Scn
+and
+.Vt Elf_Data
+descriptors associated with an ELF descriptor and recovers them
+when the descriptor is closed using
+.Xr elf_end 3 .
+Thus the application must not call
+.Xr free 3
+on data structures allocated by the ELF library.
+.Pp
+Conversely the library will not
+free data that it has not allocated.
+As an example, an application may call
+.Xr elf_newdata 3
+to allocate a new
+.Vt Elf_Data
+descriptor and can set the
+.Va d_off
+member of the descriptor to point to a region of memory allocated
+using
+.Xr malloc 3 .
+It is the applications responsibility to free this arena, though the
+library will reclaim the space used by the
+.Vt Elf_Data
+descriptor itself.
+.Sh SEE ALSO
+.Xr gelf 3 ,
+.Xr elf 5
+.Sh HISTORY
+The original ELF(3) API was developed for Unix System V.
+The current implementation of the ELF(3) API appeared in
+.Fx 7.0 .
+.Sh AUTHORS
+The ELF library was written by
+.An Joseph Koshy Aq Mt jkoshy@FreeBSD.org .
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (c) 2006,2008,2011 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: elf.c 2225 2011-11-26 18:55:54Z jkoshy $");
+
+struct _libelf_globals _libelf = {
+	.libelf_arch		= LIBELF_ARCH,
+	.libelf_byteorder	= LIBELF_BYTEORDER,
+	.libelf_class		= LIBELF_CLASS,
+	.libelf_error		= 0,
+	.libelf_fillchar	= 0,
+	.libelf_version		= EV_NONE
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_begin.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,315 @@
+.\" Copyright (c) 2006,2008-2011 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_begin.3 3182 2015-04-10 16:08:10Z emaste $
+.\"
+.Dd December 11, 2011
+.Os
+.Dt ELF_BEGIN 3
+.Sh NAME
+.Nm elf_begin
+.Nd open an ELF file or ar(1) archive
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft "Elf *"
+.Fn elf_begin "int fd" "Elf_Cmd cmd" "Elf *elf"
+.Sh DESCRIPTION
+Function
+.Fn elf_begin
+is used to open ELF files and
+.Xr ar 1
+archives for further processing by other APIs in the
+.Xr elf 3
+library.
+It is also used to access individual ELF members of an
+.Xr ar 1
+archive in combination with the
+.Xr elf_next 3
+and
+.Xr elf_rand 3
+APIs.
+.Pp
+Argument
+.Ar fd
+is an open file descriptor returned from an
+.Xr open 2
+system call.
+Function
+.Fn elf_begin
+uses argument
+.Ar fd
+for reading or writing depending on the value of argument
+.Ar cmd .
+Argument
+.Ar elf
+is primarily used for iterating through archives.
+.Pp
+The argument
+.Ar cmd
+can have the following values:
+.Bl -tag -width "ELF_C_WRITE"
+.It ELF_C_NULL
+Causes
+.Fn elf_begin
+to return NULL.
+Arguments
+.Ar fd
+and
+.Ar elf
+are ignored, and no additional error is signalled.
+.It ELF_C_READ
+This value is to be when the application wishes to examine (but not
+modify) the contents of the file specified by the arguments
+.Ar fd
+and
+.Ar elf .
+It can be used for both
+.Xr ar 1
+archives and for ELF objects.
+.Pp
+If argument
+.Ar elf
+is NULL, the library will allocate a new ELF descriptor for the file
+being processed.
+The argument
+.Ar fd
+should have been opened for reading.
+.Pp
+If argument
+.Ar elf
+is not NULL, and references a regular ELF file previously opened with
+.Fn elf_begin ,
+then the activation count for the descriptor referenced by argument
+.Ar elf
+is incremented.
+The value in argument
+.Ar fd
+should match that used to open the descriptor argument
+.Ar elf .
+.Pp
+If argument
+.Ar elf
+is not NULL, and references a descriptor for an
+.Xr ar 1
+archive opened earlier with
+.Fn elf_begin ,
+a descriptor for an element in the archive is returned as
+described in the section
+.Sx "Processing ar(1) archives"
+below.
+The value for argument
+.Ar fd
+should match that used to open the archive earlier.
+.Pp
+If argument
+.Ar elf
+is not NULL, and references an
+.Xr ar 1
+archive opened earlier with
+.Fn elf_memory ,
+then the value of the argument
+.Ar fd
+is ignored.
+.It Dv ELF_C_RDWR
+This command is used to prepare an ELF file for reading and writing.
+This command is not supported for
+.Xr ar 1
+archives.
+.Pp
+Argument
+.Ar fd
+should have been opened for reading and writing.
+If argument
+.Ar elf
+is NULL, the library will allocate a new ELF descriptor for
+the file being processed.
+If the argument
+.Ar elf
+is non-null, it should point to a descriptor previously
+allocated with
+.Fn elf_begin
+with the same values for arguments
+.Ar fd
+and
+.Ar cmd ;
+in this case the library will increment the activation count for descriptor
+.Ar elf
+and return the same descriptor.
+.Pp
+Changes to the in-memory image of the ELF file may be written back to
+disk using the
+.Xr elf_update 3
+function.
+.It Dv ELF_C_WRITE
+This command is used when the application wishes to create a new ELF
+file.
+Argument
+.Ar fd
+should have been opened for writing.
+Argument
+.Ar elf
+is ignored, and the previous contents of file referenced by argument
+.Ar fd
+are overwritten.
+.El
+.Ss Processing ar(1) archives
+An
+.Xr ar 1
+archive may be opened in read mode (with argument
+.Ar cmd
+set to
+.Dv ELF_C_READ )
+using
+.Fn elf_begin
+or
+.Fn elf_memory .
+The returned ELF descriptor can be passed into to
+subsequent calls to
+.Fn elf_begin
+to access individual members of the archive.
+.Pp
+Random access within an opened archive is possible using
+the
+.Xr elf_next 3
+and
+.Xr elf_rand 3
+functions.
+.Pp
+The symbol table of the archive may be retrieved
+using
+.Xr elf_getarsym 3 .
+.Sh RETURN VALUES
+The function returns a pointer to a ELF descriptor if successful, or NULL
+if an error occurred.
+.Sh EXAMPLES
+To iterate through the members of an
+.Xr ar 1
+archive, use:
+.Bd -literal -offset indent
+Elf_Cmd c;
+Elf *ar_e, *elf_e;
+\&...
+c = ELF_C_READ;
+if ((ar_e = elf_begin(fd, c, (Elf *) 0)) == 0) {
+	\&... handle error in opening the archive ...
+}
+while ((elf_e = elf_begin(fd, c, ar_e)) != 0) {
+	\&... process member referenced by elf_e here ...
+	c = elf_next(elf_e);
+	elf_end(elf_e);
+}
+.Ed
+.Pp
+To create a new ELF file, use:
+.Bd -literal -offset indent
+int fd;
+Elf *e;
+\&...
+if ((fd = open("filename", O_RDWR|O_TRUNC|O_CREAT, 0666)) < 0) {
+	\&... handle the error from open(2) ...
+}
+if ((e = elf_begin(fd, ELF_C_WRITE, (Elf *) 0)) == 0) {
+	\&... handle the error from elf_begin() ...
+}
+\&... create the ELF image using other elf(3) APIs ...
+elf_update(e, ELF_C_WRITE);
+elf_end(e);
+.Ed
+.Sh ERRORS
+Function
+.Fn elf_begin
+can fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARCHIVE
+The archive denoted by argument
+.Ar elf
+could not be parsed.
+.It Bq Er ELF_E_ARGUMENT
+The value in argument
+.Ar cmd
+was unrecognized.
+.It Bq Er ELF_E_ARGUMENT
+A non-null value for argument
+.Ar elf
+was specified when
+.Ar cmd
+was set to
+.Dv ELF_C_RDWR .
+.It Bq Er ELF_E_ARGUMENT
+The value of argument
+.Ar fd
+differs from the one the ELF descriptor
+.Ar elf
+was created with.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar cmd
+differs from the value specified when ELF descriptor
+.Ar elf
+was created.
+.It Bq Er ELF_E_ARGUMENT
+An
+.Xr ar 1
+archive was opened with
+.Ar cmd
+set to
+.Dv ELF_C_RDWR .
+.It Bq Er ELF_E_ARGUMENT
+The file referenced by argument
+.Ar fd
+was empty.
+.It Bq Er ELF_E_ARGUMENT
+The underlying file for argument
+.Ar fd
+was of an unsupported type.
+.It Bq Er ELF_E_IO
+The file descriptor in argument
+.Ar fd
+was invalid.
+.It Bq Er ELF_E_IO
+The file descriptor in argument
+.Ar fd
+could not be read or written to.
+.It Bq Er ELF_E_RESOURCE
+An out of memory condition was encountered.
+.It Bq Er ELF_E_SEQUENCE
+Function
+.Fn elf_begin
+was called before a working version was established with
+.Xr elf_version 3 .
+.It Bq Er ELF_E_VERSION
+The ELF object referenced by argument
+.Ar fd
+was of an unsupported ELF version.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_end 3 ,
+.Xr elf_errno 3 ,
+.Xr elf_memory 3 ,
+.Xr elf_next 3 ,
+.Xr elf_rand 3 ,
+.Xr elf_update 3 ,
+.Xr gelf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_begin.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,91 @@
+/*-
+ * Copyright (c) 2006,2008-2011 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: elf_begin.c 2364 2011-12-28 17:55:25Z jkoshy $");
+
+Elf *
+elf_begin(int fd, Elf_Cmd c, Elf *a)
+{
+	Elf *e;
+
+	e = NULL;
+
+	if (LIBELF_PRIVATE(version) == EV_NONE) {
+		LIBELF_SET_ERROR(SEQUENCE, 0);
+		return (NULL);
+	}
+
+	switch (c) {
+	case ELF_C_NULL:
+		return (NULL);
+
+	case ELF_C_WRITE:
+		/*
+		 * The ELF_C_WRITE command is required to ignore the
+		 * descriptor passed in.
+		 */
+		a = NULL;
+		break;
+
+	case ELF_C_RDWR:
+		if (a != NULL) { /* not allowed for ar(1) archives. */
+			LIBELF_SET_ERROR(ARGUMENT, 0);
+			return (NULL);
+		}
+		/*FALLTHROUGH*/
+	case ELF_C_READ:
+		/*
+		 * Descriptor `a' could be for a regular ELF file, or
+		 * for an ar(1) archive.  If descriptor `a' was opened
+		 * using a valid file descriptor, we need to check if
+		 * the passed in `fd' value matches the original one.
+		 */
+		if (a &&
+		    ((a->e_fd != -1 && a->e_fd != fd) || c != a->e_cmd)) {
+			LIBELF_SET_ERROR(ARGUMENT, 0);
+			return (NULL);
+		}
+		break;
+
+	default:
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+
+	}
+
+	if (a == NULL)
+		e = _libelf_open_object(fd, c, 1);
+	else if (a->e_kind == ELF_K_AR)
+		e = _libelf_ar_open_member(a->e_fd, c, a);
+	else
+		(e = a)->e_activations++;
+
+	return (e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_cntl.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,111 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_cntl.3 3181 2015-04-10 13:22:51Z emaste $
+.\"
+.Dd August 9, 2006
+.Os
+.Dt ELF_CNTL 3
+.Sh NAME
+.Nm elf_cntl
+.Nd control an elf file descriptor
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft int
+.Fn elf_cntl "Elf *elf" "Elf_Cmd cmd"
+.Sh DESCRIPTION
+Function
+.Fn elf_cntl
+controls the ELF library's subsequent use of the file descriptor
+used to create ELF descriptor
+.Ar elf .
+.Pp
+Argument
+.Ar cmd
+informs the library of the action to be taken:
+.Bl -tag -width "ELF_C_FDDONE"
+.It Dv ELF_C_FDDONE
+This value instructs the ELF library not to perform any further
+I/O on the file descriptor associated with argument
+.Ar elf .
+For ELF descriptors opened with mode
+.Ar ELF_C_WRITE
+or
+.Ar ELF_C_RDWR
+subsequent
+.Fn elf_update
+operations on the descriptor will fail.
+.It Dv ELF_C_FDREAD
+This value instructs the ELF library to read in all necessary
+data associated with ELF descriptor
+.Ar elf
+into memory so that the underlying file descriptor can be
+safely closed with command
+.Dv ELF_C_FDDONE .
+.El
+.Pp
+Argument
+.Ar elf
+must be an ELF descriptor associated with a file system object
+(e.g., an
+.Xr ar 1
+archive, an ELF file, or other data file).
+.Sh IMPLEMENTATION NOTES
+Due to use of
+.Xr mmap 2
+internally, this function is a no-op for ELF objects opened in
+.Dv ELF_C_READ
+mode.
+.Sh RETURN VALUES
+Function
+.Fn elf_cntl
+returns 0 on success, or -1 if an error was detected.
+.Sh ERRORS
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARCHIVE
+Argument
+.Ar elf
+is a descriptor for an archive member.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was NULL.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar cmd
+was not recognized.
+.It Bq Er ELF_E_MODE
+An
+.Dv ELF_C_FDREAD
+operation was requested on an ELF descriptor opened
+for writing.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_begin 3 ,
+.Xr elf_end 3 ,
+.Xr elf_next 3 ,
+.Xr elf_update 3 ,
+.Xr gelf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_cntl.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: elf_cntl.c 2225 2011-11-26 18:55:54Z jkoshy $");
+
+int
+elf_cntl(Elf *e, Elf_Cmd c)
+{
+	if (e == NULL ||
+	    (c != ELF_C_FDDONE && c != ELF_C_FDREAD)) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (-1);
+	}
+
+	if (e->e_parent) {
+		LIBELF_SET_ERROR(ARCHIVE, 0);
+		return (-1);
+	}
+
+	if (c == ELF_C_FDREAD) {
+		if (e->e_cmd == ELF_C_WRITE) {
+			LIBELF_SET_ERROR(MODE, 0);
+			return (-1);
+		}
+		else
+			return (0);
+	}
+
+	e->e_fd = -1;
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_data.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,276 @@
+/*-
+ * Copyright (c) 2006,2008,2011 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <libelf.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: elf_data.c 3466 2016-05-11 18:35:44Z emaste $");
+
+Elf_Data *
+elf_getdata(Elf_Scn *s, Elf_Data *ed)
+{
+	Elf *e;
+	unsigned int sh_type;
+	int elfclass, elftype;
+	size_t count, fsz, msz;
+	struct _Libelf_Data *d;
+	uint64_t sh_align, sh_offset, sh_size;
+	int (*xlate)(unsigned char *_d, size_t _dsz, unsigned char *_s,
+	    size_t _c, int _swap);
+
+	d = (struct _Libelf_Data *) ed;
+
+	if (s == NULL || (e = s->s_elf) == NULL ||
+	    (d != NULL && s != d->d_scn)) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	assert(e->e_kind == ELF_K_ELF);
+
+	if (d == NULL && (d = STAILQ_FIRST(&s->s_data)) != NULL)
+		return (&d->d_data);
+
+	if (d != NULL)
+		return (&STAILQ_NEXT(d, d_next)->d_data);
+
+	if (e->e_rawfile == NULL) {
+		/*
+		 * In the ELF_C_WRITE case, there is no source that
+		 * can provide data for the section.
+		 */
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	elfclass = e->e_class;
+
+	assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64);
+
+	if (elfclass == ELFCLASS32) {
+		sh_type   = s->s_shdr.s_shdr32.sh_type;
+		sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset;
+		sh_size   = (uint64_t) s->s_shdr.s_shdr32.sh_size;
+		sh_align  = (uint64_t) s->s_shdr.s_shdr32.sh_addralign;
+	} else {
+		sh_type   = s->s_shdr.s_shdr64.sh_type;
+		sh_offset = s->s_shdr.s_shdr64.sh_offset;
+		sh_size   = s->s_shdr.s_shdr64.sh_size;
+		sh_align  = s->s_shdr.s_shdr64.sh_addralign;
+	}
+
+	if (sh_type == SHT_NULL) {
+		LIBELF_SET_ERROR(SECTION, 0);
+		return (NULL);
+	}
+
+	if ((elftype = _libelf_xlate_shtype(sh_type)) < ELF_T_FIRST ||
+	    elftype > ELF_T_LAST || (sh_type != SHT_NOBITS &&
+	    (sh_offset > e->e_rawsize || sh_size > e->e_rawsize - sh_offset))) {
+		LIBELF_SET_ERROR(SECTION, 0);
+		return (NULL);
+	}
+
+	if ((fsz = (elfclass == ELFCLASS32 ? elf32_fsize : elf64_fsize)
+            (elftype, (size_t) 1, e->e_version)) == 0) {
+		LIBELF_SET_ERROR(UNIMPL, 0);
+		return (NULL);
+	}
+
+	if (sh_size % fsz) {
+		LIBELF_SET_ERROR(SECTION, 0);
+		return (NULL);
+	}
+
+	if (sh_size / fsz > SIZE_MAX) {
+		LIBELF_SET_ERROR(RANGE, 0);
+		return (NULL);
+	}
+
+	count = (size_t) (sh_size / fsz);
+
+	msz = _libelf_msize(elftype, elfclass, e->e_version);
+
+	if (count > 0 && msz > SIZE_MAX / count) {
+		LIBELF_SET_ERROR(RANGE, 0);
+		return (NULL);
+	}
+
+	assert(msz > 0);
+	assert(count <= SIZE_MAX);
+	assert(msz * count <= SIZE_MAX);
+
+	if ((d = _libelf_allocate_data(s)) == NULL)
+		return (NULL);
+
+	d->d_data.d_buf     = NULL;
+	d->d_data.d_off     = 0;
+	d->d_data.d_align   = sh_align;
+	d->d_data.d_size    = msz * count;
+	d->d_data.d_type    = elftype;
+	d->d_data.d_version = e->e_version;
+
+	if (sh_type == SHT_NOBITS || sh_size == 0) {
+	        STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
+		return (&d->d_data);
+        }
+
+	if ((d->d_data.d_buf = malloc(msz * count)) == NULL) {
+		(void) _libelf_release_data(d);
+		LIBELF_SET_ERROR(RESOURCE, 0);
+		return (NULL);
+	}
+
+	d->d_flags  |= LIBELF_F_DATA_MALLOCED;
+
+	xlate = _libelf_get_translator(elftype, ELF_TOMEMORY, elfclass);
+	if (!(*xlate)(d->d_data.d_buf, (size_t) d->d_data.d_size,
+	    e->e_rawfile + sh_offset, count,
+	    e->e_byteorder != LIBELF_PRIVATE(byteorder))) {
+		_libelf_release_data(d);
+		LIBELF_SET_ERROR(DATA, 0);
+		return (NULL);
+	}
+
+	STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
+
+	return (&d->d_data);
+}
+
+Elf_Data *
+elf_newdata(Elf_Scn *s)
+{
+	Elf *e;
+	struct _Libelf_Data *d;
+
+	if (s == NULL || (e = s->s_elf) == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	assert(e->e_kind == ELF_K_ELF);
+
+	/*
+	 * elf_newdata() has to append a data descriptor, so
+	 * bring in existing section data if not already present.
+	 */
+	if (e->e_rawfile && s->s_size > 0 && STAILQ_EMPTY(&s->s_data))
+		if (elf_getdata(s, NULL) == NULL)
+			return (NULL);
+
+	if ((d = _libelf_allocate_data(s)) == NULL)
+		return (NULL);
+
+	STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
+
+	d->d_data.d_align = 1;
+	d->d_data.d_buf = NULL;
+	d->d_data.d_off = (uint64_t) ~0;
+	d->d_data.d_size = 0;
+	d->d_data.d_type = ELF_T_BYTE;
+	d->d_data.d_version = LIBELF_PRIVATE(version);
+
+	(void) elf_flagscn(s, ELF_C_SET, ELF_F_DIRTY);
+
+	return (&d->d_data);
+}
+
+/*
+ * Retrieve a data descriptor for raw (untranslated) data for section
+ * `s'.
+ */
+
+Elf_Data *
+elf_rawdata(Elf_Scn *s, Elf_Data *ed)
+{
+	Elf *e;
+	int elf_class;
+	uint32_t sh_type;
+	struct _Libelf_Data *d;
+	uint64_t sh_align, sh_offset, sh_size;
+
+	if (s == NULL || (e = s->s_elf) == NULL || e->e_rawfile == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	assert(e->e_kind == ELF_K_ELF);
+
+	d = (struct _Libelf_Data *) ed;
+
+	if (d == NULL && (d = STAILQ_FIRST(&s->s_rawdata)) != NULL)
+		return (&d->d_data);
+
+	if (d != NULL)
+		return (&STAILQ_NEXT(d, d_next)->d_data);
+
+	elf_class = e->e_class;
+
+	assert(elf_class == ELFCLASS32 || elf_class == ELFCLASS64);
+
+	if (elf_class == ELFCLASS32) {
+		sh_type   = s->s_shdr.s_shdr32.sh_type;
+		sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset;
+		sh_size   = (uint64_t) s->s_shdr.s_shdr32.sh_size;
+		sh_align  = (uint64_t) s->s_shdr.s_shdr32.sh_addralign;
+	} else {
+		sh_type   = s->s_shdr.s_shdr64.sh_type;
+		sh_offset = s->s_shdr.s_shdr64.sh_offset;
+		sh_size   = s->s_shdr.s_shdr64.sh_size;
+		sh_align  = s->s_shdr.s_shdr64.sh_addralign;
+	}
+
+	if (sh_type == SHT_NULL) {
+		LIBELF_SET_ERROR(SECTION, 0);
+		return (NULL);
+	}
+
+	if (sh_type != SHT_NOBITS &&
+	    (sh_offset > e->e_rawsize || sh_size > e->e_rawsize - sh_offset)) {
+		LIBELF_SET_ERROR(SECTION, 0);
+		return (NULL);
+	}
+
+	if ((d = _libelf_allocate_data(s)) == NULL)
+		return (NULL);
+
+	d->d_data.d_buf = (sh_type == SHT_NOBITS || sh_size == 0) ? NULL :
+	    e->e_rawfile + sh_offset;
+	d->d_data.d_off     = 0;
+	d->d_data.d_align   = sh_align;
+	d->d_data.d_size    = sh_size;
+	d->d_data.d_type    = ELF_T_BYTE;
+	d->d_data.d_version = e->e_version;
+
+	STAILQ_INSERT_TAIL(&s->s_rawdata, d, d_next);
+
+	return (&d->d_data);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_end.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,76 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_end.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd June 29, 2006
+.Os
+.Dt ELF_END 3
+.Sh NAME
+.Nm elf_end
+.Nd release an ELF descriptor
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft int
+.Fn elf_end "Elf *elf"
+.Sh DESCRIPTION
+Function
+.Fn elf_end
+is used to release the resources associated with an ELF descriptor
+pointed to by argument
+.Ar elf .
+This descriptor must have been allocated by a previous call to
+.Xr elf_begin 3
+or
+.Xr elf_memory 3 .
+For programming convenience, a NULL value is permitted for argument
+.Ar elf .
+.Pp
+A call to
+.Fn elf_end
+decrements the activation count for descriptor
+.Ar elf
+by one.
+The resources associated with the descriptor are only released
+with its activation count goes to zero.
+.Pp
+Once function
+.Fn elf_end
+returns zero, the ELF descriptor
+.Ar elf
+will no longer be valid and should not be used further.
+.Sh RETURN VALUES
+Function
+.Fn elf_end
+returns the current value of the ELF descriptor
+.Ar elf Ap s
+activation count, or zero if argument
+.Ar elf
+was NULL.
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_begin 3 ,
+.Xr elf_memory 3 ,
+.Xr gelf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_end.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,95 @@
+/*-
+ * Copyright (c) 2006,2008-2009,2011 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <libelf.h>
+#include <stdlib.h>
+
+#include "_libelf.h"
+
+#if	ELFTC_HAVE_MMAP
+#include <sys/mman.h>
+#endif
+
+ELFTC_VCSID("$Id: elf_end.c 3174 2015-03-27 17:13:41Z emaste $");
+
+int
+elf_end(Elf *e)
+{
+	Elf *sv;
+	Elf_Scn *scn, *tscn;
+
+	if (e == NULL || e->e_activations == 0)
+		return (0);
+
+	if (--e->e_activations > 0)
+		return (e->e_activations);
+
+	assert(e->e_activations == 0);
+
+	while (e && e->e_activations == 0) {
+		switch (e->e_kind) {
+		case ELF_K_AR:
+			/*
+			 * If we still have open child descriptors, we
+			 * need to defer reclaiming resources till all
+			 * the child descriptors for the archive are
+			 * closed.
+			 */
+			if (e->e_u.e_ar.e_nchildren > 0)
+				return (0);
+			break;
+		case ELF_K_ELF:
+			/*
+			 * Reclaim all section descriptors.
+			 */
+			STAILQ_FOREACH_SAFE(scn, &e->e_u.e_elf.e_scn, s_next,
+			    tscn)
+ 				scn = _libelf_release_scn(scn);
+			break;
+		case ELF_K_NUM:
+			assert(0);
+		default:
+			break;
+		}
+
+		if (e->e_rawfile) {
+			if (e->e_flags & LIBELF_F_RAWFILE_MALLOC)
+				free(e->e_rawfile);
+#if	ELFTC_HAVE_MMAP
+			else if (e->e_flags & LIBELF_F_RAWFILE_MMAP)
+				(void) munmap(e->e_rawfile, e->e_rawsize);
+#endif
+		}
+
+		sv = e;
+		if ((e = e->e_parent) != NULL)
+			e->e_u.e_ar.e_nchildren--;
+		sv = _libelf_release_elf(sv);
+	}
+
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_errmsg.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,107 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_errmsg.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd June 11, 2006
+.Os
+.Dt ELF_ERRMSG 3
+.Sh NAME
+.Nm elf_errmsg ,
+.Nm elf_errno
+.Nd ELF library error message handling
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft int
+.Fn elf_errno "void"
+.Ft "const char *"
+.Fn elf_errmsg "int error"
+.Sh DESCRIPTION
+When an error occurs during an ELF library API call, the library
+encodes the error using an error number and stores the error number
+internally for retrieval by the application at a later point of time.
+Error numbers may contain an OS supplied error code in addition to
+an ELF API specific error code.
+An error number value of zero indicates no error.
+.Pp
+Function
+.Fn elf_errno
+is used to retrieve the last error recorded by the ELF library.
+Invoking this function has the side-effect of resetting the
+ELF library's recorded error number to zero.
+.Pp
+The function
+.Fn elf_errmsg
+returns a null-terminated string with a human readable
+description of the error specified in argument
+.Ar error .
+A zero value for argument
+.Ar error
+retrieves the most recent error encountered by the ELF
+library.
+An argument value of -1 behaves identically, except that
+it guarantees a non-NULL return from
+.Fn elf_errmsg .
+.Sh RETURN VALUES
+Function
+.Fn elf_errno
+returns a non-zero value encoding the last error encountered
+by the ELF library, or zero if no error was encountered.
+.Pp
+Function
+.Fn elf_errmsg
+returns a pointer to library local storage for non-zero values
+of argument
+.Ar error .
+With a zero argument, the function will return a NULL pointer if no
+error had been encountered by the library, or will return a pointer to
+library local storage containing an appropriate message otherwise.
+.Sh EXAMPLES
+Clearing the ELF library's recorded error number can be accomplished
+by invoking
+.Fn elf_errno
+and discarding its return value.
+.Bd -literal -offset indent
+/* clear error */
+(void) elf_errno();
+.Ed
+.Pp
+Retrieving a human-readable description of the current error number
+can be done with the following snippet:
+.Bd -literal -offset indent
+int err;
+const char *errmsg;
+\&...
+err = elf_errno();
+if (err != 0)
+	errmsg = elf_errmsg(err);
+.Ed
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr gelf 3
+.Sh BUGS
+Function
+.Fn elf_errmsg
+is not localized.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_errmsg.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,83 @@
+/*-
+ * Copyright (c) 2006,2008,2011 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <libelf.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: elf_errmsg.c 3174 2015-03-27 17:13:41Z emaste $");
+
+/*
+ * Retrieve a human readable translation for an error message.
+ */
+
+static const char *_libelf_errors[] = {
+#define	DEFINE_ERROR(N,S)	[ELF_E_##N] = S
+	DEFINE_ERROR(NONE,	"No Error"),
+	DEFINE_ERROR(ARCHIVE,	"Malformed ar(1) archive"),
+	DEFINE_ERROR(ARGUMENT,	"Invalid argument"),
+	DEFINE_ERROR(CLASS,	"ELF class mismatch"),
+	DEFINE_ERROR(DATA,	"Invalid data buffer descriptor"),
+	DEFINE_ERROR(HEADER,	"Missing or malformed ELF header"),
+	DEFINE_ERROR(IO,	"I/O error"),
+	DEFINE_ERROR(LAYOUT,	"Layout constraint violation"),
+	DEFINE_ERROR(MODE,	"Incorrect ELF descriptor mode"),
+	DEFINE_ERROR(RANGE,	"Value out of range of target"),
+	DEFINE_ERROR(RESOURCE,	"Resource exhaustion"),
+	DEFINE_ERROR(SECTION,	"Invalid section descriptor"),
+	DEFINE_ERROR(SEQUENCE,	"API calls out of sequence"),
+	DEFINE_ERROR(UNIMPL,	"Unimplemented feature"),
+	DEFINE_ERROR(VERSION,	"Unknown ELF API version"),
+	DEFINE_ERROR(NUM,	"Unknown error")
+#undef	DEFINE_ERROR
+};
+
+const char *
+elf_errmsg(int error)
+{
+	int oserr;
+
+	if (error == ELF_E_NONE &&
+	    (error = LIBELF_PRIVATE(error)) == 0)
+	    return NULL;
+	else if (error == -1)
+	    error = LIBELF_PRIVATE(error);
+
+	oserr = error >> LIBELF_OS_ERROR_SHIFT;
+	error &= LIBELF_ELF_ERROR_MASK;
+
+	if (error < ELF_E_NONE || error >= ELF_E_NUM)
+		return _libelf_errors[ELF_E_NUM];
+	if (oserr) {
+		(void) snprintf((char *) LIBELF_PRIVATE(msg),
+		    sizeof(LIBELF_PRIVATE(msg)), "%s: %s",
+		    _libelf_errors[error], strerror(oserr));
+		return (const char *)&LIBELF_PRIVATE(msg);
+	}
+	return _libelf_errors[error];
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_errno.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,41 @@
+/*-
+ * Copyright (c) 2006,2008,2011 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: elf_errno.c 3174 2015-03-27 17:13:41Z emaste $");
+
+int
+elf_errno(void)
+{
+	int old;
+
+	old = LIBELF_PRIVATE(error);
+	LIBELF_PRIVATE(error) = 0;
+	return (old & LIBELF_ELF_ERROR_MASK);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_fill.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,52 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_fill.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd June 11, 2006
+.Os
+.Dt ELF_FILL 3
+.Sh NAME
+.Nm elf_fill
+.Nd set fill byte for inter-section padding
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft void
+.Fn elf_fill "int fill"
+.Sh DESCRIPTION
+Function
+.Fn elf_fill
+allows an application to specify a fill value for the padding inserted
+between two sections of an ELF file to meet section alignment
+constraints.
+By default the ELF library uses zero bytes for padding.
+.Pp
+The ELF library will only pad bytes if the
+.Dv ELF_F_LAYOUT
+flag is not set for the ELF file.
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_flagelf 3 ,
+.Xr gelf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_fill.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: elf_fill.c 3174 2015-03-27 17:13:41Z emaste $");
+
+void
+elf_fill(int fill)
+{
+	LIBELF_PRIVATE(fillchar) = fill;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_flag.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,196 @@
+/*-
+ * Copyright (c) 2006,2008-2009,2011 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: elf_flag.c 3174 2015-03-27 17:13:41Z emaste $");
+
+unsigned int
+elf_flagarhdr(Elf_Arhdr *a, Elf_Cmd c, unsigned int flags)
+{
+	unsigned int r;
+
+	if (a == NULL)
+		return (0);
+
+	if ((c != ELF_C_SET && c != ELF_C_CLR) ||
+	    (flags & ~ELF_F_DIRTY) != 0) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	if (c == ELF_C_SET)
+		r = a->ar_flags |= flags;
+	else
+		r = a->ar_flags &= ~flags;
+
+	return (r & LIBELF_F_API_MASK);
+}
+
+unsigned int
+elf_flagdata(Elf_Data *d, Elf_Cmd c, unsigned int flags)
+{
+	unsigned int r;
+	struct _Libelf_Data *ld;
+
+	if (d == NULL)
+		return (0);
+
+	if ((c != ELF_C_SET && c != ELF_C_CLR) ||
+	    (flags & ~ELF_F_DIRTY) != 0) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	ld = (struct _Libelf_Data *) d;
+
+	if (c == ELF_C_SET)
+		r = ld->d_flags |= flags;
+	else
+		r = ld->d_flags &= ~flags;
+
+	return (r & LIBELF_F_API_MASK);
+}
+
+unsigned int
+elf_flagehdr(Elf *e, Elf_Cmd c, unsigned int flags)
+{
+	int ec;
+	void *ehdr;
+
+	if (e == NULL)
+		return (0);
+
+	if ((c != ELF_C_SET && c != ELF_C_CLR) ||
+	    (e->e_kind != ELF_K_ELF) || (flags & ~ELF_F_DIRTY) != 0 ||
+	    ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	if (ec == ELFCLASS32)
+		ehdr = e->e_u.e_elf.e_ehdr.e_ehdr32;
+	else
+		ehdr = e->e_u.e_elf.e_ehdr.e_ehdr64;
+
+	if (ehdr == NULL) {
+		LIBELF_SET_ERROR(SEQUENCE, 0);
+		return (0);
+	}
+
+	return (elf_flagelf(e, c, flags));
+}
+
+unsigned int
+elf_flagelf(Elf *e, Elf_Cmd c, unsigned int flags)
+{
+	unsigned int r;
+
+	if (e == NULL)
+		return (0);
+
+	if ((c != ELF_C_SET && c != ELF_C_CLR) ||
+	    (e->e_kind != ELF_K_ELF) ||
+	    (flags & ~(ELF_F_ARCHIVE | ELF_F_ARCHIVE_SYSV |
+	    ELF_F_DIRTY | ELF_F_LAYOUT)) != 0) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	if ((flags & ELF_F_ARCHIVE_SYSV) && (flags & ELF_F_ARCHIVE) == 0) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	if ((flags & ELF_F_ARCHIVE) && e->e_cmd != ELF_C_WRITE) {
+		LIBELF_SET_ERROR(MODE, 0);
+		return (0);
+	}
+
+	if (c == ELF_C_SET)
+		r = e->e_flags |= flags;
+	else
+		r = e->e_flags &= ~flags;
+	return (r & LIBELF_F_API_MASK);
+}
+
+unsigned int
+elf_flagphdr(Elf *e, Elf_Cmd c, unsigned int flags)
+{
+	int ec;
+	void *phdr;
+
+	if (e == NULL)
+		return (0);
+
+	if ((c != ELF_C_SET && c != ELF_C_CLR) ||
+	    (e->e_kind != ELF_K_ELF) || (flags & ~ELF_F_DIRTY) != 0 ||
+	    ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	if (ec == ELFCLASS32)
+		phdr = e->e_u.e_elf.e_phdr.e_phdr32;
+	else
+		phdr = e->e_u.e_elf.e_phdr.e_phdr64;
+
+	if (phdr == NULL) {
+		LIBELF_SET_ERROR(SEQUENCE, 0);
+		return (0);
+	}
+
+	return (elf_flagelf(e, c, flags));
+}
+
+unsigned int
+elf_flagscn(Elf_Scn *s, Elf_Cmd c, unsigned int flags)
+{
+	unsigned int r;
+
+	if (s == NULL)
+		return (0);
+
+	if ((c != ELF_C_SET && c != ELF_C_CLR) ||
+	    (flags & ~ELF_F_DIRTY) != 0) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	if (c == ELF_C_SET)
+		r = s->s_flags |= flags;
+	else
+		r = s->s_flags &= ~flags;
+	return (r & LIBELF_F_API_MASK);
+}
+
+unsigned int
+elf_flagshdr(Elf_Scn *s, Elf_Cmd c, unsigned int flags)
+{
+	return (elf_flagscn(s, c, flags));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_flagdata.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,223 @@
+.\" Copyright (c) 2006-2008,2011 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_flagdata.3 3479 2016-06-25 20:44:33Z jkoshy $
+.\"
+.Dd December 3, 2011
+.Os
+.Dt ELF_FLAGDATA 3
+.Sh NAME
+.Nm elf_flagarhdr ,
+.Nm elf_flagdata ,
+.Nm elf_flagehdr ,
+.Nm elf_flagelf ,
+.Nm elf_flagphdr ,
+.Nm elf_flagscn ,
+.Nm elf_flagshdr
+.Nd manipulate flags associated with ELF(3) data structures
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft "unsigned int"
+.Fn elf_flagarhdr "Elf_Arhdr *arhdr" "Elf_Cmd cmd" "unsigned int flags"
+.Ft "unsigned int"
+.Fn elf_flagdata "Elf_Data *data" "Elf_Cmd cmd" "unsigned int flags"
+.Ft "unsigned int"
+.Fn elf_flagehdr "Elf *elf" "Elf_Cmd cmd" "unsigned int flags"
+.Ft "unsigned int"
+.Fn elf_flagelf "Elf *elf" "Elf_Cmd cmd" "unsigned int flags"
+.Ft "unsigned int"
+.Fn elf_flagphdr "Elf *elf" "Elf_Cmd cmd" "unsigned int flags"
+.Ft "unsigned int"
+.Fn elf_flagscn "Elf_Scn *scn" "Elf_Cmd cmd" "unsigned int flags"
+.Ft "unsigned int"
+.Fn elf_flagshdr "Elf_Scn *scn" "Elf_Cmd cmd" "unsigned int flags"
+.Sh DESCRIPTION
+These functions are used to query, set or reset flags on data
+structures associated with an ELF file.
+.Pp
+Arguments
+.Ar arhdr ,
+.Ar data ,
+.Ar elf
+and
+.Ar scn
+denote the data structures whose flags need to be changed.
+These values should have been returned by prior calls to
+functions in the ELF(3) API set:
+.Bl -bullet -compact
+.It
+Argument
+.Ar arhdr
+should have been returned by a prior call to
+.Xr elf_getarhdr 3 .
+.It
+Argument
+.Ar data
+should have been returned by a prior call to one of
+.Xr elf_newdata 3 ,
+.Xr elf_getdata 3
+or
+.Xr elf_rawdata 3 .
+.It
+Argument
+.Ar elf
+should have been allocated by a prior call to one of
+.Xr elf_begin 3
+or
+.Xr elf_memory 3 .
+.It
+Argument
+.Ar scn
+should have been returned by a prior call to one of
+.Xr elf_getscn 3 ,
+.Xr elf_newscn 3
+or
+.Xr elf_nextscn 3 .
+.El
+These values are allowed to be NULL to simplify error handling in
+application code.
+.Pp
+Argument
+.Ar cmd
+may have the following values:
+.Bl -tag -width ELF_C_SET
+.It Dv ELF_C_CLR
+The argument
+.Ar flags
+specifies the flags to be cleared.
+.It Dv ELF_C_SET
+The argument
+.Ar flags
+specifies the flags to be set.
+.El
+.Pp
+The argument
+.Ar flags
+is allowed to have the following flags set:
+.Bl -tag -width ELF_F_ARCHIVE_SYSV
+.It Dv ELF_F_ARCHIVE
+This flag is only valid with the
+.Fn elf_flagelf
+API.
+It informs the library that the application desires to create an
+.Xr ar 1
+archive.
+Argument
+.Ar elf
+should have been opened for writing using the
+.Dv ELF_C_WRITE
+command to function
+.Fn elf_begin .
+.It Dv ELF_F_ARCHIVE_SYSV
+This flag is used in conjunction with the
+.Dv ELF_F_ARCHIVE
+flag to indicate that library should create archives that conform
+to System V layout rules.
+The default is to create BSD style archives.
+.It Dv ELF_F_DIRTY
+Mark the associated data structure as needing to be written back
+to the underlying file.
+A subsequent call to
+.Xr elf_update 3
+will resynchronize the library's internal data structures.
+.It Dv ELF_F_LAYOUT
+This flag is only valid with the
+.Fn elf_flagelf
+API.
+It informs the library that the application will take
+responsibility for the layout of the file and that the library is
+not to insert any padding in between sections.
+.El
+.Pp
+Marking a given data structure as
+.Dq dirty
+affects all of its contained elements.
+Thus marking an ELF descriptor
+.Ar elf
+with
+.Fn elf_flagelf "elf" "ELF_C_SET" "ELF_F_DIRTY"
+means that the entire contents of the descriptor are
+.Dq dirty .
+.Pp
+Using a value of zero for argument
+.Ar flags
+will return the current set of flags for the data structure being
+queried.
+.Sh RETURN VALUES
+These functions return the updated flags if successful, or zero if
+an error is detected.
+.Sh COMPATIBILITY
+The
+.Fn elf_flagarhdr
+function and the
+.Dv ELF_F_ARCHIVE
+and
+.Dv ELF_F_ARCHIVE_SYSV
+flags are an extension to the ELF(3) API.
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+An unsupported value was used for the
+.Ar cmd
+argument.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar flags
+had unsupported flags set.
+.It Bq Er ELF_E_ARGUMENT
+The argument
+.Ar elf
+was not a descriptor for an ELF object.
+.It Bq Er ELF_E_MODE
+The
+.Dv ELF_F_ARCHIVE
+flag was used with an ELF descriptor that had not been opened for writing.
+.It Bq Er ELF_E_SEQUENCE
+Function
+.Fn elf_flagehdr
+was called without an executable header being allocated.
+.It Bq Er ELF_E_SEQUENCE
+Function
+.Fn elf_flagphdr
+was called without a program header being allocated.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf32_newehdr 3 ,
+.Xr elf32_newphdr 3 ,
+.Xr elf64_newehdr 3 ,
+.Xr elf64_newphdr 3 ,
+.Xr elf_newdata 3 ,
+.Xr elf_update 3 ,
+.Xr gelf 3 ,
+.Xr gelf_newehdr 3 ,
+.Xr gelf_newphdr 3 ,
+.Xr gelf_update_dyn 3 ,
+.Xr gelf_update_move 3 ,
+.Xr gelf_update_rel 3 ,
+.Xr gelf_update_rela 3 ,
+.Xr gelf_update_sym 3 ,
+.Xr gelf_update_syminfo 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_getarhdr.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,97 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_getarhdr.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd August 15, 2006
+.Os
+.Dt ELF_GETARHDR 3
+.Sh NAME
+.Nm elf_getarhdr
+.Nd retrieve ar(1) header for an archive member
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft "Elf_Arhdr *"
+.Fn elf_getarhdr "Elf *elf"
+.Sh DESCRIPTION
+The
+.Fn elf_getarhdr
+function returns a pointer to an archive member header for
+a descriptor
+.Ar elf .
+This descriptor must have been returned by a prior call to
+.Xr elf_begin 3 ,
+and must be a descriptor for a member inside an
+.Xr ar 1
+archive.
+.Pp
+Structure
+.Vt Elf_Arhdr
+includes the following members:
+.Bl -tag -width indent
+.It Vt "char *" Va ar_name
+A pointer to a null terminated string containing the translated
+name of the archive member.
+.It Vt "char *" Va ar_rawname
+A pointer to a null terminated string containing the untranslated
+name for the archive member, including all
+.Xr ar 1
+formatting characters and trailing white space.
+.It Vt time_t Va ar_date
+The timestamp associated with the member.
+.It Vt uid_t Va ar_uid
+The uid of the creator of the member.
+.It Vt gid_t Va ar_gid
+The gid of the creator of the member.
+.It Vt mode_t Va ar_mode
+The file mode of the member.
+.It Vt size_t Va ar_size
+The size of the member in bytes.
+.El
+.Sh RETURN VALUES
+This function returns a valid pointer to an
+.Vt Elf_Arhdr
+structure if successful, or NULL if an error is encountered.
+.Sh ERRORS
+Function
+.Fn elf_getarhdr
+may fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was NULL.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was not a descriptor for a member of an
+.Xr ar 1
+archive.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_begin 3 ,
+.Xr elf_getarsym 3 ,
+.Xr elf_memory 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_getarhdr.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 2006,2008,2010 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: elf_getarhdr.c 3174 2015-03-27 17:13:41Z emaste $");
+
+Elf_Arhdr *
+elf_getarhdr(Elf *e)
+{
+	if (e == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	if (e->e_flags & LIBELF_F_AR_HEADER)
+		return (e->e_hdr.e_arhdr);
+
+	return (_libelf_ar_gethdr(e));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_getarsym.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,130 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_getarsym.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd August 15, 2006
+.Os
+.Dt ELF_GETARSYM 3
+.Sh NAME
+.Nm elf_getarsym
+.Nd retrieve the symbol table of an archive
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft "Elf_Arsym *"
+.Fn elf_getarsym "Elf *elf" "size_t *ptr"
+.Sh DESCRIPTION
+The function
+.Fn elf_getarsym
+retrieves the symbol table for an
+.Xr ar 1
+archive, if one is available.
+.Pp
+Argument
+.Ar elf
+should be a descriptor for an
+.Xr ar 1
+archive opened using
+.Fn elf_begin
+or
+.Fn elf_memory .
+.Pp
+If the archive
+.Ar elf
+contains a symbol table with n entries, this function returns a
+pointer to an array of n+1
+.Vt Elf_Arsym
+structures.
+An
+.Vt Elf_Arsym
+structure has the following elements:
+.Bl -tag -width indent -compact
+.It Vt "char *" Va as_name
+This structure member is a pointer to a null-terminated symbol name.
+.It Vt "off_t" Va as_off
+This structure member contains the byte offset from the beginning of the archive to
+the header for the archive member.
+This value is suitable for use with
+.Xr elf_rand 3 .
+.It Vt "unsigned long" Va as_hash
+This structure member contains a portable hash value for the symbol
+name, as computed by
+.Xr elf_hash 3 .
+.El
+.Pp
+The last entry of the returned array will have a NULL value for member
+.Va as_name ,
+a zero value for member
+.Va as_off
+and an illegal value of ~0UL for
+.Va as_hash .
+.Pp
+If argument
+.Ar ptr
+is non-null, the
+.Fn elf_getarsym
+function will store the number of table entries returned (including the
+sentinel entry at the end) into the location it points to.
+.Sh RETURN VALUES
+Function
+.Fn elf_getarsym
+returns a pointer to an array of
+.Vt Elf_Arsym
+structures if successful, or a NULL
+pointer if an error was encountered.
+.Pp
+If argument
+.Ar ptr
+is non-null and there was no error, the library will store the
+number of archive symbol entries returned into the location it
+points to.
+If argument
+.Ar ptr
+is non-null and an error was encountered, the library will
+set the location pointed to by it to zero.
+.Sh ERRORS
+Function
+.Fn elf_getarsym
+may fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was NULL.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was not a descriptor for an
+.Xr ar 1
+archive.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_begin 3 ,
+.Xr elf_getarhdr 3 ,
+.Xr elf_hash 3 ,
+.Xr elf_memory 3 ,
+.Xr elf_next 3 ,
+.Xr elf_rand 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_getarsym.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: elf_getarsym.c 3174 2015-03-27 17:13:41Z emaste $");
+
+Elf_Arsym *
+elf_getarsym(Elf *ar, size_t *ptr)
+{
+	size_t n;
+	Elf_Arsym *symtab;
+
+	n = 0;
+	symtab = NULL;
+
+	if (ar == NULL || ar->e_kind != ELF_K_AR)
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+	else if ((symtab = ar->e_u.e_ar.e_symtab) != NULL)
+		n = ar->e_u.e_ar.e_symtabsz;
+	else if (ar->e_u.e_ar.e_rawsymtab)
+		symtab = (ar->e_flags & LIBELF_F_AR_VARIANT_SVR4) ?
+		    _libelf_ar_process_svr4_symtab(ar, &n) :
+		    _libelf_ar_process_bsd_symtab(ar, &n);
+	else
+		LIBELF_SET_ERROR(ARCHIVE, 0);
+
+	if (ptr)
+		*ptr = n;
+	return (symtab);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_getbase.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,71 @@
+.\" Copyright (c) 2006,2008,2010 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_getbase.3 978 2010-06-06 12:40:19Z jkoshy $
+.\"
+.Dd June 6, 2010
+.Os
+.Dt ELF_GETBASE 3
+.Sh NAME
+.Nm elf_getbase
+.Nd get the base offset for an object file
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft off_t
+.Fn elf_getbase "Elf *elf"
+.Sh DESCRIPTION
+Function
+.Fn elf_getbase
+returns the file offset to the first byte of the object referenced by ELF
+descriptor
+.Ar elf .
+.Pp
+For descriptors referencing members of archives, the returned offset is
+the file offset of the member in its containing archive.
+For descriptors to regular objects, the returned offset is (vacuously)
+zero.
+.Sh RETURN VALUES
+Function
+.Fn elf_getbase
+returns a valid file offset if successful, or
+.Pq Vt off_t
+.Li -1
+in case of an error.
+.Sh ERRORS
+Function
+.Fn elf_getbase
+may fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was NULL.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_getarhdr 3 ,
+.Xr elf_getident 3 ,
+.Xr elf_rawfile 3 ,
+.Xr gelf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_getbase.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: elf_getbase.c 3174 2015-03-27 17:13:41Z emaste $");
+
+off_t
+elf_getbase(Elf *e)
+{
+	if (e == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return ((off_t) -1);
+	}
+
+	if (e->e_parent == NULL)
+		return ((off_t) 0);
+
+	return ((off_t) ((uintptr_t) e->e_rawfile -
+	    (uintptr_t) e->e_parent->e_rawfile));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_getdata.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,229 @@
+.\" Copyright (c) 2006,2008,2010-2011 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_getdata.3 3181 2015-04-10 13:22:51Z emaste $
+.\"
+.Dd January 26, 2011
+.Os
+.Dt ELF_GETDATA 3
+.Sh NAME
+.Nm elf_getdata ,
+.Nm elf_newdata ,
+.Nm elf_rawdata
+.Nd iterate through or allocate section data
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft "Elf_Data *"
+.Fn elf_getdata "Elf_Scn *scn" "Elf_Data *data"
+.Ft "Elf_Data *"
+.Fn elf_newdata "Elf_Scn *scn"
+.Ft "Elf_Data *"
+.Fn elf_rawdata "Elf_Scn *scn" "Elf_Data *data"
+.Sh DESCRIPTION
+These functions are used to access and manipulate data descriptors
+associated with section descriptors.
+Data descriptors used by the ELF library are described in
+.Xr elf 3 .
+.Pp
+Function
+.Fn elf_getdata
+will return the next data descriptor associated with section descriptor
+.Ar scn .
+The returned data descriptor will be setup to contain translated data.
+Argument
+.Ar data
+may be NULL, in which case the function returns the first data descriptor
+associated with section
+.Ar scn .
+If argument
+.Ar data
+is not NULL, it must be a pointer to a data descriptor associated with
+section descriptor
+.Ar scn ,
+and function
+.Fn elf_getdata
+will return a pointer to the next data descriptor for the section,
+or NULL when the end of the section's descriptor list is reached.
+.Pp
+Function
+.Fn elf_newdata
+will allocate a new data descriptor and append it to the list of data
+descriptors associated with section descriptor
+.Ar scn .
+The new data descriptor will be initialized as follows:
+.Bl -tag -width "d_version" -compact -offset indent
+.It Va d_align
+Set to 1.
+.It Va d_buf
+Initialized to NULL.
+.It Va d_off
+Set to (off_t) -1.
+This field is under application control if the
+.Dv ELF_F_LAYOUT
+flag was set on the ELF descriptor.
+.It Va d_size
+Set to zero.
+.It Va d_type
+Initialized to
+.Dv ELF_T_BYTE .
+.It Va d_version
+Set to the current working version of the library, as set by
+.Xr elf_version 3 .
+.El
+The application must set these values as appropriate before
+calling
+.Xr elf_update 3 .
+Section
+.Ar scn
+must be associated with an ELF file opened for writing.
+If the application has not requested full control of layout by
+setting the
+.Dv ELF_F_LAYOUT
+flag on descriptor
+.Ar elf ,
+then the data referenced by the returned descriptor will be positioned
+after the existing content of the section, honoring the file alignment
+specified in member
+.Va d_align .
+On successful completion of a call to
+.Fn elf_newdata ,
+the ELF library will mark the section
+.Ar scn
+as
+.Dq dirty .
+.Pp
+Function
+.Fn elf_rawdata
+is used to step through the data descriptors associated with
+section
+.Ar scn .
+In contrast to function
+.Fn elf_getdata ,
+this function returns untranslated data.
+If argument
+.Ar data
+is NULL, the first data descriptor associated with section
+.Ar scn
+is returned.
+If argument
+.Ar data
+is not NULL, is must be a data descriptor associated with
+section
+.Ar scn ,
+and function
+.Fn elf_rawdata
+will return the next data descriptor in the list, or NULL
+if no further descriptors are present.
+Function
+.Fn elf_rawdata
+always returns
+.Vt Elf_Data
+structures of type
+.Dv ELF_T_BYTE .
+.Ss Special handling of zero-sized and SHT_NOBITS sections
+For sections of type
+.Dv SHT_NOBITS,
+and for zero-sized sections,
+the functions
+.Fn elf_getdata
+and
+.Fn elf_rawdata
+return a pointer to a valid
+.Vt Elf_Data
+structure that has its
+.Va d_buf
+member set to NULL and its
+.Va d_size
+member set to the size of the section.
+.Pp
+If an application wishes to create a section of type
+.Dv SHT_NOBITS ,
+it should add a data buffer to the section using function
+.Fn elf_newdata .
+It should then set the
+.Va d_buf
+and
+.Va d_size
+members of the returned
+.Vt Elf_Data
+structure to NULL and the desired size of the section respectively.
+.Sh RETURN VALUES
+These functions return a valid pointer to a data descriptor if successful, or
+NULL if an error occurs.
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+Either of the arguments
+.Ar scn
+or
+.Ar data
+was NULL.
+.It Bq Er ELF_E_ARGUMENT
+The data descriptor referenced by argument
+.Ar data
+is not associated with section descriptor
+.Ar scn .
+.It Bq Er ELF_E_ARGUMENT
+The section denoted by argument
+.Ar scn
+had no data associated with it.
+.It Bq Er ELF_E_DATA
+Retrieval of data from the underlying object failed.
+.It Bq Er ELF_E_RESOURCE
+An out of memory condition was detected.
+.It Bq Er ELF_E_SECTION
+Section
+.Ar scn
+had type
+.Dv SHT_NULL .
+.It Bq Er ELF_E_SECTION
+The type of the section
+.Ar scn
+was not recognized by the library.
+.It Bq Er ELF_E_SECTION
+The size of the section
+.Ar scn
+is not a multiple of the file size for its section type.
+.It Bq Er ELF_E_SECTION
+The file offset for section
+.Ar scn
+is incorrect.
+.It Bq Er ELF_E_UNIMPL
+The section type associated with section
+.Ar scn
+is currently unsupported by the library.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_flagdata 3 ,
+.Xr elf_flagscn 3 ,
+.Xr elf_getscn 3 ,
+.Xr elf_getshdr 3 ,
+.Xr elf_newscn 3 ,
+.Xr elf_rawfile 3 ,
+.Xr elf_update 3 ,
+.Xr elf_version 3 ,
+.Xr gelf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_getident.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,83 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_getident.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd July 3, 2006
+.Os
+.Dt ELF_GETIDENT 3
+.Sh NAME
+.Nm elf_getident
+.Nd return the initial bytes of a file
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft char *
+.Fn elf_getident "Elf *elf" "size_t *sz"
+.Sh DESCRIPTION
+Function
+.Fn elf_getident
+returns a pointer to the initial bytes of the file for descriptor
+.Ar elf .
+.Pp
+If argument
+.Ar sz
+is non-null, the size of the identification area returned is written
+to the location pointed to by
+.Ar sz .
+This location is set to zero on errors.
+.Sh RETURN VALUES
+Function
+.Fn elf_getident
+will return a non-NULL pointer to the initial bytes of the file if
+successful, or NULL if an error condition is detected.
+.Sh ERRORS
+Function
+.Fn elf_getident
+can fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+A NULL value was passed in for argument
+.Ar elf .
+.It Bq Er ELF_E_SEQUENCE
+ELF descriptor
+.Ar elf
+was opened for writing and function
+.Fn elf_getident
+was called before a call to
+.Xr elf_update 3 .
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf32_getehdr 3 ,
+.Xr elf64_getehdr 3 ,
+.Xr elf_getarhdr 3 ,
+.Xr elf_getbase 3 ,
+.Xr elf_getflags 3 ,
+.Xr elf_kind 3 ,
+.Xr elf_rawfile 3 ,
+.Xr elf_update 3 ,
+.Xr gelf 3 ,
+.Xr gelf_getclass 3 ,
+.Xr gelf_getehdr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_getident.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <ar.h>
+#include <assert.h>
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: elf_getident.c 3174 2015-03-27 17:13:41Z emaste $");
+
+char *
+elf_getident(Elf *e, size_t *sz)
+{
+
+	if (e == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		goto error;
+	}
+
+	if (e->e_cmd == ELF_C_WRITE && e->e_rawfile == NULL) {
+		LIBELF_SET_ERROR(SEQUENCE, 0);
+		goto error;
+	}
+
+	assert(e->e_kind != ELF_K_AR || e->e_cmd == ELF_C_READ);
+
+	if (sz) {
+		if (e->e_kind == ELF_K_AR)
+			*sz = SARMAG;
+		else if (e->e_kind == ELF_K_ELF)
+			*sz = EI_NIDENT;
+		else
+			*sz = e->e_rawsize;
+	}
+
+	return ((char *) e->e_rawfile);
+
+ error:
+	if (sz)
+		*sz = 0;
+	return (NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_getphdrnum.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,86 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_getphdrnum.3 467 2009-08-05 18:18:49Z jkoshy $
+.\"
+.Dd August 5, 2009
+.Os
+.Dt ELF_GETPHDRNUM 3
+.Sh NAME
+.Nm elf_getphdrnum
+.Nd return the number of program headers in an ELF file
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft int
+.Fn elf_getphdrnum "Elf *elf" "size_t *phnum"
+.Sh DESCRIPTION
+Function
+.Fn elf_getphdrnum
+retrieves the number of ELF program headers associated with descriptor
+.Ar elf
+and stores it into the location pointed to by argument
+.Ar phnum .
+.Pp
+This routine allows applications to uniformly process both normal ELF
+objects and ELF objects that use extended numbering.
+.Pp
+.Sh RETURN VALUES
+Function
+.Fn elf_getphdrnum
+returns a zero value if successful, or -1 in case of an error.
+.Sh ERRORS
+Function
+.Fn elf_getphnum
+can fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+A NULL value was passed in for argument
+.Ar elf .
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was not for an ELF file.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+lacks an ELF Executable Header.
+.It Bq Er ELF_E_HEADER
+The ELF Executable Header associated with argument
+.Ar elf
+was corrupt.
+.It Bq Er ELF_E_SECTION
+The section header at index
+.Dv SHN_UNDEF
+was corrupt.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf32_getehdr 3 ,
+.Xr elf64_getehdr 3 ,
+.Xr elf_getident 3 ,
+.Xr elf_getshdrnum 3 ,
+.Xr elf_getshdrstrndx 3 ,
+.Xr gelf 3 ,
+.Xr gelf_getehdr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_getphnum.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,93 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_getphnum.3 467 2009-08-05 18:18:49Z jkoshy $
+.\"
+.Dd August 5, 2009
+.Os
+.Dt ELF_GETPHNUM 3
+.Sh NAME
+.Nm elf_getphnum
+.Nd return the number of program headers in an ELF file
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft int
+.Fn elf_getphnum "Elf *elf" "size_t *phnum"
+.Sh DESCRIPTION
+This function is deprecated.
+Please use function
+.Xr elf_getphdrnum 3
+instead.
+.Pp
+Function
+.Fn elf_getphnum
+retrieves the number of ELF program headers associated with descriptor
+.Ar elf
+and stores it into the location pointed to by argument
+.Ar phnum .
+.Pp
+This routine allows applications to uniformly process both normal ELF
+objects and ELF objects that use extended numbering.
+.Pp
+.Sh RETURN VALUES
+Function
+.Fn elf_getphnum
+returns a non-zero value if successful, or zero in case of an
+error.
+.Sh ERRORS
+Function
+.Fn elf_getphnum
+can fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+A NULL value was passed in for argument
+.Ar elf .
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was not for an ELF file.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+lacks an ELF Executable Header.
+.It Bq Er ELF_E_HEADER
+The ELF Executable Header associated with argument
+.Ar elf
+was corrupt.
+.It Bq Er ELF_E_SECTION
+The section header at index
+.Dv SHN_UNDEF
+was corrupt.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf32_getehdr 3 ,
+.Xr elf64_getehdr 3 ,
+.Xr elf_getident 3 ,
+.Xr elf_getphdrnum 3 ,
+.Xr elf_getshdrnum 3 ,
+.Xr elf_getshdrstrndx 3 ,
+.Xr gelf 3 ,
+.Xr gelf_getehdr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_getscn.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,151 @@
+.\" Copyright (c) 2006-2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_getscn.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd October 22, 2007
+.Os
+.Dt ELF_GETSCN 3
+.Sh NAME
+.Nm elf_getscn ,
+.Nm elf_ndxscn ,
+.Nm elf_newscn ,
+.Nm elf_nextscn
+.Nd get/allocate section information for an ELF object
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft "Elf_Scn *"
+.Fn elf_getscn "Elf *elf" "size_t index"
+.Ft size_t
+.Fn elf_ndxscn "Elf_Scn *scn"
+.Ft "Elf_Scn *"
+.Fn elf_newscn "Elf *elf"
+.Ft "Elf_Scn *"
+.Fn elf_nextscn "Elf *elf" "Elf_Scn *scn"
+.Sh DESCRIPTION
+These functions are used to iterate through the sections associated
+with an ELF descriptor.
+.Pp
+Function
+.Fn elf_getscn
+will return a section descriptor for the section at index
+.Ar index
+in the object denoted by ELF descriptor
+.Ar elf .
+An error will be signalled if the specified section does not
+exist.
+.Pp
+Function
+.Fn elf_ndxscn
+returns the section table index associated with section descriptor
+.Ar scn .
+.Pp
+Function
+.Fn elf_newscn
+creates a new section and appends it to the list of sections
+associated with descriptor
+.Ar elf .
+The library will automatically increment the
+.Va e_shnum
+field of the ELF header associated with descriptor
+.Ar elf ,
+and will set the
+.Dv ELF_F_DIRTY
+flag on the returned section descriptor.
+For ELF descriptors opened for writing, the ELF library will
+automatically create an empty section at index zero
+.Dv ( SHN_UNDEF )
+on the first call to
+.Fn elf_newscn .
+.Pp
+Function
+.Fn elf_nextscn
+takes a section descriptor
+.Ar scn
+and returns a pointer to the section descriptor at the next higher
+index.
+Argument
+.Ar scn
+is allowed to be NULL, in which case this function will return a
+pointer to the section descriptor at index 1.
+If no further sections are present, function
+.Fn elf_nextscn
+will return a NULL pointer.
+.Sh RETURN VALUES
+Functions
+.Fn elf_getscn ,
+.Fn elf_newscn
+and
+.Fn elf_nextscn
+return a valid pointer to a section descriptor if successful, or
+NULL if an error occurs.
+.Pp
+Function
+.Fn elf_ndxscn
+returns a valid section table index if successful, or
+.Dv SHN_UNDEF
+if an error occurs.
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+Arguments
+.Ar elf
+or
+.Ar scn
+were NULL.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar index
+exceeded the current number of sections in the ELF object.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was not a descriptor for an ELF file.
+.It Bq Er ELF_E_ARGUMENT
+Section descriptor
+.Ar scn
+was not associated with ELF descriptor
+.Ar elf .
+.It Bq Er ELF_E_CLASS
+Descriptor
+.Ar elf
+was of an unknown ELF class.
+.It Bq Er ELF_E_SECTION
+Argument
+.Ar elf
+specified extended section numbering in the ELF header with the section header at
+index
+.Dv SHN_UNDEF
+not being of type
+.Dv SHT_NULL .
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_flagdata 3 ,
+.Xr elf_flagscn 3 ,
+.Xr elf_getdata 3 ,
+.Xr elf_getshdr 3 ,
+.Xr gelf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_getshdrnum.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,78 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_getshdrnum.3 467 2009-08-05 18:18:49Z jkoshy $
+.\"
+.Dd August 4, 2009
+.Os
+.Dt ELF_GETSHDRNUM 3
+.Sh NAME
+.Nm elf_getshdrnum
+.Nd return the number of sections in an ELF file
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft int
+.Fn elf_getshdrnum "Elf *elf" "size_t *shnum"
+.Sh DESCRIPTION
+Function
+.Fn elf_getshdrnum
+retrieves the number of ELF sections associated with descriptor
+.Ar elf
+and stores it into the location pointed to by argument
+.Ar shnum .
+.Pp
+This routine allows applications to uniformly process both normal ELF
+objects, and ELF objects that use extended section numbering.
+.Pp
+.Sh RETURN VALUES
+Function
+.Fn elf_getshdrnum
+returns zero value if successful, or -1 in case of an error.
+.Sh ERRORS
+Function
+.Fn elf_getshdrnum
+can fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+A NULL value was passed in for argument
+.Ar elf .
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was not for an ELF file.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+lacks an ELF Executable header.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf32_getehdr 3 ,
+.Xr elf64_getehdr 3 ,
+.Xr elf_getident 3 ,
+.Xr elf_getphdrnum 3 ,
+.Xr elf_getshdrstrndx 3 ,
+.Xr gelf 3 ,
+.Xr gelf_getehdr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_getshdrstrndx.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,79 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_getshdrstrndx.3 467 2009-08-05 18:18:49Z jkoshy $
+.\"
+.Dd August 5, 2009
+.Os
+.Dt ELF_GETSHDRSTRNDX 3
+.Sh NAME
+.Nm elf_getshdrstrndx
+.Nd retrieve the index of the section name string table
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft int
+.Fn elf_getshdrstrndx "Elf *elf" "size_t *ndxptr"
+.Sh DESCRIPTION
+Function
+.Fn elf_getshdrstrndx
+retrieves the section index of the string table containing section
+names from descriptor
+.Ar elf
+and stores it into the location pointed to by argument
+.Ar ndxptr .
+.Pp
+This function allow applications to process both normal ELF
+objects and ELF objects that use extended section numbering uniformly.
+.Pp
+.Sh RETURN VALUES
+These functions return zero if successful, or -1 in case of an error.
+.Sh ERRORS
+These functions can fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+A NULL value was passed in for argument
+.Ar elf .
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was not for an ELF file.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+lacks an ELF Executable header.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar ndx
+contained a value in the reserved range of section indices.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf32_getehdr 3 ,
+.Xr elf64_getehdr 3 ,
+.Xr elf_getident 3 ,
+.Xr elf_getphdrnum 3 ,
+.Xr elf_getshdrnum 3 ,
+.Xr gelf 3 ,
+.Xr gelf_getehdr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_getshnum.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,84 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_getshnum.3 467 2009-08-05 18:18:49Z jkoshy $
+.\"
+.Dd August 5, 2009
+.Os
+.Dt ELF_GETSHNUM 3
+.Sh NAME
+.Nm elf_getshnum
+.Nd return the number of sections in an ELF file
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft int
+.Fn elf_getshnum "Elf *elf" "size_t *shnum"
+.Sh DESCRIPTION
+This function is deprecated.
+Please use
+.Xr elf_getshdrnum 3
+instead.
+.Pp
+Function
+.Fn elf_getshnum
+retrieves the number of ELF sections associated with descriptor
+.Ar elf
+and stores it into the location pointed to by argument
+.Ar shnum .
+.Pp
+This routine allows applications to uniformly process both normal ELF
+objects, and ELF objects that use extended section numbering.
+.Pp
+.Sh RETURN VALUES
+Function
+.Fn elf_getshnum
+returns a non-zero value if successful, or zero in case of an
+error.
+.Sh ERRORS
+Function
+.Fn elf_getshnum
+can fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+A NULL value was passed in for argument
+.Ar elf .
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was not for an ELF file.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+lacks an ELF Executable header.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf32_getehdr 3 ,
+.Xr elf64_getehdr 3 ,
+.Xr elf_getident 3 ,
+.Xr elf_getphdrnum 3 ,
+.Xr elf_getshdrstrndx 3 ,
+.Xr gelf 3 ,
+.Xr gelf_getehdr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_getshstrndx.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,94 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_getshstrndx.3 467 2009-08-05 18:18:49Z jkoshy $
+.\"
+.Dd August 5, 2009
+.Os
+.Dt ELF_GETSHSTRNDX 3
+.Sh NAME
+.Nm elf_getshstrndx ,
+.Nm elf_setshstrndx
+.Nd retrieve/update the index of the section name string table
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft int
+.Fn elf_getshstrndx "Elf *elf" "size_t *ndxptr"
+.Ft int
+.Fn elf_setshstrndx "Elf *elf" "size_t ndx"
+.Sh DESCRIPTION
+Function
+.Fn elf_getshstrndx
+retrieves the section index of the string table containing section
+names from descriptor
+.Ar elf
+and stores it into the location pointed to by argument
+.Ar ndxptr .
+Function
+.Fn elf_getshstrndx
+is deprecated.
+Please use
+.Xr elf_getshdrstrndx 3
+instead.
+.Pp
+Function
+.Fn elf_setshstrndx
+sets the index of the section name string table to argument
+.Ar ndx .
+.Pp
+These routines allow applications to process both normal ELF
+objects and ELF objects that use extended section numbering uniformly.
+.Pp
+.Sh RETURN VALUES
+These functions return a non-zero value if successful, or zero in case
+of an error.
+.Sh ERRORS
+These functions can fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+A NULL value was passed in for argument
+.Ar elf .
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was not for an ELF file.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+lacks an ELF Executable header.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar ndx
+contained a value in the reserved range of section indices.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf32_getehdr 3 ,
+.Xr elf64_getehdr 3 ,
+.Xr elf_getident 3 ,
+.Xr elf_getphdrnum 3 ,
+.Xr elf_getshdrnum 3 ,
+.Xr gelf 3 ,
+.Xr gelf_getehdr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_hash.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,57 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_hash.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd August 15, 2006
+.Os
+.Dt ELF_HASH 3
+.Sh NAME
+.Nm elf_hash
+.Nd compute a hash value for a string
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft "unsigned long"
+.Fn elf_hash "const char *name"
+.Sh DESCRIPTION
+Function
+.Fn elf_hash
+computes a portable hash value for the null terminated string
+pointed to by argument
+.Ar name .
+.Pp
+The hash value returned is will be identical across
+machines of different architectures.
+This allows hash tables to be built on one machine and
+correctly used on another of a different architecture.
+The hash value returned is also guaranteed
+.Em not
+to be the bit pattern of all ones (~0UL).
+.Sh IMPLEMENTATION NOTES
+The library internally uses unsigned 32 bit arithmetic to compute
+the hash value.
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr gelf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_hash.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: elf_hash.c 3174 2015-03-27 17:13:41Z emaste $");
+
+/*
+ * This elf_hash function is defined by the System V ABI.
+ */
+
+unsigned long
+elf_hash(const char *name)
+{
+	unsigned long h, t;
+	const unsigned char *s;
+
+	s = (const unsigned char *) name;
+	h = t = 0;
+
+	for (; *s != '\0'; h = h & ~t) {
+		h = (h << 4) + *s++;
+		t = h & 0xF0000000UL;
+		if (t)
+			h ^= t >> 24;
+	}
+
+	return (h);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_kind.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,71 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_kind.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd June 1, 2006
+.Os
+.Dt ELF_KIND 3
+.Sh NAME
+.Nm elf_kind
+.Nd determine ELF file type
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft Elf_Kind
+.Fn elf_kind "Elf *elf"
+.Sh DESCRIPTION
+The
+.Fn elf_kind
+function identifies the kind of file associated with its argument
+.Ar elf .
+The argument
+.Ar elf
+is allowed to be NULL.
+.Sh RETURN VALUES
+The
+.Fn elf_kind
+function returns one of the following values:
+.Bl -tag -width indent
+.It Dv ELF_K_AR
+The file associated with argument
+.Ar elf
+is an archive.
+.It Dv ELF_K_ELF
+The file associated with argument
+.Ar elf
+is an ELF file.
+.It Dv ELF_K_NONE
+The argument
+.Ar elf
+was NULL, or the ELF library could not determine the type of the file
+associated with argument
+.Ar elf ,
+or an error occurred when processing.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_begin 3 ,
+.Xr elf_getident 3 ,
+.Xr gelf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_kind.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,42 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: elf_kind.c 3174 2015-03-27 17:13:41Z emaste $");
+
+Elf_Kind
+elf_kind(Elf *e)
+{
+	if (e == NULL)
+		return (ELF_K_NONE);
+	if (e->e_kind == ELF_K_AR ||
+	    e->e_kind == ELF_K_ELF)
+		return (e->e_kind);
+	return (ELF_K_NONE);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_memory.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,122 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_memory.3 2314 2011-12-11 06:19:51Z jkoshy $
+.\"
+.Dd June 28, 2006
+.Os
+.Dt ELF_MEMORY 3
+.Sh NAME
+.Nm elf_memory
+.Nd process an ELF or ar(1) archive mapped into memory
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft "Elf *"
+.Fn elf_memory "char *image" "size_t size"
+.Sh DESCRIPTION
+Function
+.Fn elf_memory
+is used to process an ELF file or
+.Xr ar 1
+archive whose image is present in memory.
+.Pp
+Argument
+.Ar image
+points to the start of the memory image of the file or archive.
+Argument
+.Ar size
+contains the size in bytes of the memory image.
+.Pp
+The ELF descriptor is created for reading (i.e., analogous to the
+use of
+.Xr elf_begin 3
+with a command argument value of
+.Dv ELF_C_READ Ns ).
+.Sh RETURN VALUES
+Function
+.Fn elf_memory
+returns a pointer to a new ELF descriptor if successful, or NULL if an
+error occurred.
+.Pp
+The return value may be queried for the file type using
+.Xr elf_kind 3 .
+.Sh EXAMPLES
+To read parse an elf file, use:
+.Bd -literal -offset indent
+int fd;
+void *p;
+struct stat sb;
+Elf *e;
+\&...
+if ((fd = open("./elf-file", O_RDONLY)) < 0 ||
+    fstat(fd, &sb) < 0 ||
+    (p = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, (off_t) 0)) ==
+    MAP_FAILED) {
+	... handle system error ...
+}
+
+if ((e = elf_memory(p, sb.st_size)) == NULL) {
+	... handle elf(3) error ...
+}
+\&... use ELF descriptor "e" here ...
+.Ed
+.Sh ERRORS
+Function
+.Fn elf_memory
+can fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+A NULL value was used for argument
+.Ar image
+or the value of argument
+.Ar sz
+was zero.
+.It Bq Er ELF_E_HEADER
+The header of the ELF object contained an unsupported value in its
+.Va e_ident[EI_CLASS]
+field.
+.It Bq Er ELF_E_HEADER
+The header of the ELF object contained an unsupported value in its
+.Va e_ident[EI_DATA]
+field.
+.It Bq Er ELF_E_RESOURCE
+An out of memory condition was detected.
+.It Bq Er ELF_E_SEQUENCE
+Function
+.Fn elf_memory
+was called before a working version was set using
+.Xr elf_version 3 .
+.It Bq Er ELF_E_VERSION
+The ELF object referenced by argument
+.Ar image
+was of an unsupported ELF version.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_begin 3 ,
+.Xr elf_end 3 ,
+.Xr elf_errno 3 ,
+.Xr elf_kind 3 ,
+.Xr gelf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_memory.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: elf_memory.c 3013 2014-03-23 06:16:59Z jkoshy $");
+
+Elf *
+elf_memory(char *image, size_t sz)
+{
+	if (LIBELF_PRIVATE(version) == EV_NONE) {
+		LIBELF_SET_ERROR(SEQUENCE, 0);
+		return (NULL);
+	}
+
+	if (image == NULL || sz == 0) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	return (_libelf_memory((unsigned char *) image, sz, 1));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_next.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,96 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_next.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd June 17, 2006
+.Os
+.Dt ELF_NEXT 3
+.Sh NAME
+.Nm elf_next
+.Nd provide sequential access to the next archive member
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft Elf_Cmd
+.Fn elf_next "Elf *elf"
+.Sh DESCRIPTION
+The
+.Fn elf_next
+function causes the ELF archive descriptor corresponding to argument
+.Ar elf
+to be adjusted to provide access to the next member in
+the archive on a subsequent call to
+.Fn elf_begin .
+.Pp
+The return value of
+.Fn elf_next
+is suitable for use in a loop invoking
+.Fn elf_begin .
+.Sh RETURN VALUES
+If successful, function
+.Fn elf_next
+returns the value
+.Dv ELF_C_READ .
+Otherwise, if argument
+.Ar elf
+was not associated with an archive, or if it was
+.Dv NULL ,
+or if any other error occurred, the value
+.Dv ELF_C_NULL
+is returned.
+.Sh EXAMPLES
+To process all the members of an archive use:
+.Bd -literal -offset indent
+Elf_Cmd cmd;
+Elf *archive, *e;
+\&...
+cmd = ELF_C_READ;
+archive = elf_begin(fd, cmd, NULL);
+while ((e = elf_begin(fd, cmd, archive)) != (Elf *) 0)
+{
+	... process `e' here ...
+
+	cmd = elf_next(e);
+	elf_end(e);
+}
+elf_end(archive);
+.Ed
+.Sh ERRORS
+Function
+.Fn elf_next
+may fail with the following error:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was not associated with a containing
+.Xr ar 1
+archive.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_begin 3 ,
+.Xr elf_end 3 ,
+.Xr elf_rand 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_next.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <ar.h>
+#include <assert.h>
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: elf_next.c 3174 2015-03-27 17:13:41Z emaste $");
+
+Elf_Cmd
+elf_next(Elf *e)
+{
+	off_t next;
+	Elf *parent;
+
+	if (e == NULL)
+		return (ELF_C_NULL);
+
+	 if ((parent = e->e_parent) == NULL) {
+		 LIBELF_SET_ERROR(ARGUMENT, 0);
+		 return (ELF_C_NULL);
+	 }
+
+	assert(parent->e_kind == ELF_K_AR);
+	assert(parent->e_cmd == ELF_C_READ);
+	assert(e->e_rawfile > parent->e_rawfile);
+
+	next = e->e_rawfile - parent->e_rawfile + (off_t) e->e_rawsize;
+	next = (next + 1) & ~1;	/* round up to an even boundary */
+
+	/*
+	 * Setup the 'e_next' field of the archive descriptor for the
+	 * next call to 'elf_begin()'.
+	 */
+	parent->e_u.e_ar.e_next = (next >= (off_t) parent->e_rawsize) ?
+	    (off_t) 0 : next;
+
+	return (ELF_C_READ);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_open.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,121 @@
+.\" Copyright (c) 2012 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_open.3 3181 2015-04-10 13:22:51Z emaste $
+.\"
+.Dd May 31, 2012
+.Os
+.Dt ELF_OPEN 3
+.Sh NAME
+.Nm elf_open
+.Nd open ELF objects and ar(1) archives
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft "Elf *"
+.Fn elf_open "int fd"
+.Ft "Elf *"
+.Fn elf_openmemory "char *image" "size_t sz"
+.Sh DESCRIPTION
+.Em Important :
+The functions
+.Fn elf_open
+and
+.Fn elf_openmemory
+are extensions to the ELF(3) API, for the internal use of the
+Elftoolchain project.
+Portable applications should not use these functions.
+.Pp
+The function
+.Fn elf_open
+returns an Elf descriptor opened with mode
+.Dv ELF_C_READ
+for the ELF object or
+.Xr ar 1
+archive referenced by the file descriptor in argument
+.Ar fd .
+.Pp
+The function
+.Fn elf_openmemory
+returns an ELF descriptor opened with mode
+.Dv ELF_C_READ
+for the ELF object or
+.Xr ar 1
+archive contained in the memory area pointed to by the argument
+.Ar image .
+The argument
+.Ar sz
+specifies the size of the memory area in bytes.
+.Sh COMPATIBILITY
+These functions are non-standard extensions to the ELF(3) API set.
+.Pp
+The behavior of these functions differs from their counterparts
+.Xr elf_begin 3
+and
+.Xr elf_memory 3
+in that these functions will successfully open malformed ELF objects
+and
+.Xr ar 1
+archives, returning an Elf descriptor of type
+.Dv ELF_K_NONE .
+.Sh RETURN VALUES
+The function returns a pointer to a ELF descriptor if successful, or
+NULL if an error occurred.
+.Sh ERRORS
+These functions can fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+The argument
+.Ar fd
+was of an unsupported file type.
+.It Bq Er ELF_E_ARGUMENT
+The argument
+.Ar sz
+was zero, or the argument
+.Ar image
+was NULL.
+.It Bq Er ELF_E_IO
+The file descriptor in argument
+.Ar fd
+was invalid.
+.It Bq Er ELF_E_IO
+The file descriptor in argument
+.Ar fd
+could not be read.
+.It Bq Er ELF_E_RESOURCE
+An out of memory condition was encountered.
+.It Bq Er ELF_E_SEQUENCE
+Functions
+.Fn elf_open
+or
+.Fn elf_openmemory
+was called before a working version was established with
+.Xr elf_version 3 .
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_begin 3 ,
+.Xr elf_errno 3 ,
+.Xr elf_memory 3 ,
+.Xr gelf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_open.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,67 @@
+/*-
+ * Copyright (c) 2011 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id$");
+
+/*
+ * Extension API: open a file for reading, ignoring parse errors.
+ */
+
+Elf *
+elf_open(int fd)
+{
+	if (LIBELF_PRIVATE(version) == EV_NONE) {
+		LIBELF_SET_ERROR(SEQUENCE, 0);
+		return (NULL);
+	}
+
+	return (_libelf_open_object(fd, ELF_C_READ, 0));
+}
+
+/*
+ * Extension API: create an ELF descriptor for an in-memory object,
+ * ignoring parse errors.
+ */
+
+Elf *
+elf_openmemory(char *image, size_t sz)
+{
+	if (LIBELF_PRIVATE(version) == EV_NONE) {
+		LIBELF_SET_ERROR(SEQUENCE, 0);
+		return (NULL);
+	}
+
+	if (image == NULL || sz == 0) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	return (_libelf_memory((unsigned char *) image, sz, 0));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_phnum.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <ar.h>
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: elf_phnum.c 3174 2015-03-27 17:13:41Z emaste $");
+
+static int
+_libelf_getphdrnum(Elf *e, size_t *phnum)
+{
+	void *eh;
+	int ec;
+
+	if (e == NULL || e->e_kind != ELF_K_ELF ||
+	    ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (-1);
+	}
+
+	if ((eh = _libelf_ehdr(e, ec, 0)) == NULL)
+		return (-1);
+
+	*phnum = e->e_u.e_elf.e_nphdr;
+
+	return (0);
+}
+
+int
+elf_getphdrnum(Elf *e, size_t *phnum)
+{
+	return (_libelf_getphdrnum(e, phnum));
+}
+
+/* Deprecated API */
+int
+elf_getphnum(Elf *e, size_t *phnum)
+{
+	return (_libelf_getphdrnum(e, phnum) >= 0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_rand.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,118 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_rand.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd June 17, 2006
+.Os
+.Dt ELF_RAND 3
+.Sh NAME
+.Nm elf_rand
+.Nd provide sequential access to the next archive member
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft off_t
+.Fn elf_rand "Elf *archive" "off_t offset"
+.Sh DESCRIPTION
+The
+.Fn elf_rand
+function causes the ELF descriptor
+.Ar archive
+to be adjusted so that the next call to
+.Xr elf_begin 3
+will provide access to the archive member at byte offset
+.Ar offset
+in the archive.
+Argument
+.Ar offset
+is the byte offset from the start of the archive to the beginning of
+the archive header for the desired member.
+.Pp
+Archive member offsets may be retrieved using the
+.Xr elf_getarsym 3
+function.
+.Sh RETURN VALUES
+Function
+.Fn elf_rand
+returns
+.Ar offset
+if successful or zero in case of an error.
+.Sh EXAMPLES
+To process all the members of an archive use:
+.Bd -literal -offset indent
+off_t off;
+Elf *archive, *e;
+\&...
+cmd = ELF_C_READ;
+archive = elf_begin(fd, cmd, NULL);
+while ((e = elf_begin(fd, cmd, archive)) != (Elf *) 0)
+{
+	... process `e' here ...
+	elf_end(e);
+
+	off = ...new value...;
+	if (elf_rand(archive, off) != off) {
+		... process error ...
+	}
+}
+elf_end(archive);
+.Ed
+.Pp
+To rewind an archive, use:
+.Bd -literal -offset indent
+Elf *archive;
+\&...
+if (elf_rand(archive, SARMAG) != SARMAG) {
+	... error ...
+}
+.Ed
+.Sh ERRORS
+Function
+.Fn elf_rand
+may fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar archive
+was null.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar archive
+was not a descriptor for an
+.Xr ar 1
+archive.
+.It Bq Er ELF_E_ARCHIVE
+Argument
+.Ar offset
+did not correspond to the start of an archive member header.
+.El
+.Sh SEE ALSO
+.Xr ar 1 ,
+.Xr elf 3 ,
+.Xr elf_begin 3 ,
+.Xr elf_end 3 ,
+.Xr elf_getarsym 3 ,
+.Xr elf_next 3 ,
+.Xr gelf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_rand.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <ar.h>
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: elf_rand.c 3174 2015-03-27 17:13:41Z emaste $");
+
+off_t
+elf_rand(Elf *ar, off_t offset)
+{
+	struct ar_hdr *arh;
+
+	if (ar == NULL || ar->e_kind != ELF_K_AR ||
+	    (offset & 1) || offset < SARMAG ||
+	    (size_t) offset + sizeof(struct ar_hdr) >= ar->e_rawsize) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return 0;
+	}
+
+	arh = (struct ar_hdr *) (ar->e_rawfile + offset);
+
+	/* a too simple sanity check */
+	if (arh->ar_fmag[0] != '`' || arh->ar_fmag[1] != '\n') {
+		LIBELF_SET_ERROR(ARCHIVE, 0);
+		return 0;
+	}
+
+	ar->e_u.e_ar.e_next = offset;
+
+	return (offset);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_rawfile.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,76 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_rawfile.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd July 3, 2006
+.Os
+.Dt ELF_RAWFILE 3
+.Sh NAME
+.Nm elf_rawfile
+.Nd return uninterpreted contents of an ELF file
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft char *
+.Fn elf_rawfile "Elf *elf" "size_t *sz"
+.Sh DESCRIPTION
+Function
+.Fn elf_rawfile
+returns the uninterpreted contents of the file referenced by ELF descriptor
+.Ar elf .
+.Pp
+If argument
+.Ar sz
+is non-null, the function stores the file's size in bytes
+in the location to which it points.
+A value of zero is written to this location if an error is
+encountered.
+.Sh RETURN VALUES
+Function
+.Fn elf_rawfile
+returns a valid pointer if successful or NULL if an error occurs.
+.Sh ERRORS
+Function
+.Fn elf_rawfile
+may fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was NULL.
+.It Bq Er ELF_E_SEQUENCE
+Argument
+.Ar elf
+was opened for writing and function
+.Fn elf_rawfile
+was invoked before
+.Xr elf_update 3 .
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_getdata 3 ,
+.Xr elf_getident 3 ,
+.Xr elf_kind 3 ,
+.Xr elf_update 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_rawfile.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: elf_rawfile.c 3174 2015-03-27 17:13:41Z emaste $");
+
+char *
+elf_rawfile(Elf *e, size_t *sz)
+{
+	size_t size;
+	unsigned char *ptr;
+
+	size = e ? e->e_rawsize : 0;
+	ptr = NULL;
+
+	if (e == NULL)
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+	else if ((ptr = e->e_rawfile) == NULL && e->e_cmd == ELF_C_WRITE)
+		LIBELF_SET_ERROR(SEQUENCE, 0);
+
+	if (sz)
+		*sz = size;
+
+	return ((char *) ptr);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_scn.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,235 @@
+/*-
+ * Copyright (c) 2006,2008-2010 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/queue.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <gelf.h>
+#include <libelf.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: elf_scn.c 3177 2015-03-30 18:19:41Z emaste $");
+
+/*
+ * Load an ELF section table and create a list of Elf_Scn structures.
+ */
+int
+_libelf_load_section_headers(Elf *e, void *ehdr)
+{
+	Elf_Scn *scn;
+	uint64_t shoff;
+	Elf32_Ehdr *eh32;
+	Elf64_Ehdr *eh64;
+	int ec, swapbytes;
+	unsigned char *src;
+	size_t fsz, i, shnum;
+	int (*xlator)(unsigned char *_d, size_t _dsz, unsigned char *_s,
+	    size_t _c, int _swap);
+
+	assert(e != NULL);
+	assert(ehdr != NULL);
+	assert((e->e_flags & LIBELF_F_SHDRS_LOADED) == 0);
+
+#define	CHECK_EHDR(E,EH)	do {				\
+		if (shoff > e->e_rawsize ||			\
+		    fsz != (EH)->e_shentsize ||			\
+		    shnum > SIZE_MAX / fsz ||			\
+		    fsz * shnum > e->e_rawsize - shoff) {	\
+			LIBELF_SET_ERROR(HEADER, 0);		\
+			return (0);				\
+		}						\
+	} while (0)
+
+	ec = e->e_class;
+	fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, (size_t) 1);
+	assert(fsz > 0);
+
+	shnum = e->e_u.e_elf.e_nscn;
+
+	if (ec == ELFCLASS32) {
+		eh32 = (Elf32_Ehdr *) ehdr;
+		shoff = (uint64_t) eh32->e_shoff;
+		CHECK_EHDR(e, eh32);
+	} else {
+		eh64 = (Elf64_Ehdr *) ehdr;
+		shoff = eh64->e_shoff;
+		CHECK_EHDR(e, eh64);
+	}
+
+	xlator = _libelf_get_translator(ELF_T_SHDR, ELF_TOMEMORY, ec);
+
+	swapbytes = e->e_byteorder != LIBELF_PRIVATE(byteorder);
+	src = e->e_rawfile + shoff;
+
+	/*
+	 * If the file is using extended numbering then section #0
+	 * would have already been read in.
+	 */
+
+	i = 0;
+	if (!STAILQ_EMPTY(&e->e_u.e_elf.e_scn)) {
+		assert(STAILQ_FIRST(&e->e_u.e_elf.e_scn) ==
+		    STAILQ_LAST(&e->e_u.e_elf.e_scn, _Elf_Scn, s_next));
+
+		i = 1;
+		src += fsz;
+	}
+
+	for (; i < shnum; i++, src += fsz) {
+		if ((scn = _libelf_allocate_scn(e, i)) == NULL)
+			return (0);
+
+		(*xlator)((unsigned char *) &scn->s_shdr, sizeof(scn->s_shdr),
+		    src, (size_t) 1, swapbytes);
+
+		if (ec == ELFCLASS32) {
+			scn->s_offset = scn->s_rawoff =
+			    scn->s_shdr.s_shdr32.sh_offset;
+			scn->s_size = scn->s_shdr.s_shdr32.sh_size;
+		} else {
+			scn->s_offset = scn->s_rawoff =
+			    scn->s_shdr.s_shdr64.sh_offset;
+			scn->s_size = scn->s_shdr.s_shdr64.sh_size;
+		}
+	}
+
+	e->e_flags |= LIBELF_F_SHDRS_LOADED;
+
+	return (1);
+}
+
+
+Elf_Scn *
+elf_getscn(Elf *e, size_t index)
+{
+	int ec;
+	void *ehdr;
+	Elf_Scn *s;
+
+	if (e == NULL || e->e_kind != ELF_K_ELF ||
+	    ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL)
+		return (NULL);
+
+	if (e->e_cmd != ELF_C_WRITE &&
+	    (e->e_flags & LIBELF_F_SHDRS_LOADED) == 0 &&
+	    _libelf_load_section_headers(e, ehdr) == 0)
+		return (NULL);
+
+	STAILQ_FOREACH(s, &e->e_u.e_elf.e_scn, s_next)
+		if (s->s_ndx == index)
+			return (s);
+
+	LIBELF_SET_ERROR(ARGUMENT, 0);
+	return (NULL);
+}
+
+size_t
+elf_ndxscn(Elf_Scn *s)
+{
+	if (s == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (SHN_UNDEF);
+	}
+	return (s->s_ndx);
+}
+
+Elf_Scn *
+elf_newscn(Elf *e)
+{
+	int ec;
+	void *ehdr;
+	Elf_Scn *scn;
+
+	if (e == NULL || e->e_kind != ELF_K_ELF) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	if ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) {
+		LIBELF_SET_ERROR(CLASS, 0);
+		return (NULL);
+	}
+
+	if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL)
+		return (NULL);
+
+	/*
+	 * The application may be asking for a new section descriptor
+	 * on an ELF object opened with ELF_C_RDWR or ELF_C_READ.  We
+	 * need to bring in the existing section information before
+	 * appending a new one to the list.
+	 *
+	 * Per the ELF(3) API, an application is allowed to open a
+	 * file using ELF_C_READ, mess with its internal structure and
+	 * use elf_update(...,ELF_C_NULL) to compute its new layout.
+	 */
+	if (e->e_cmd != ELF_C_WRITE &&
+	    (e->e_flags & LIBELF_F_SHDRS_LOADED) == 0 &&
+	    _libelf_load_section_headers(e, ehdr) == 0)
+		return (NULL);
+
+	if (STAILQ_EMPTY(&e->e_u.e_elf.e_scn)) {
+		assert(e->e_u.e_elf.e_nscn == 0);
+		if ((scn = _libelf_allocate_scn(e, (size_t) SHN_UNDEF)) ==
+		    NULL)
+			return (NULL);
+		e->e_u.e_elf.e_nscn++;
+	}
+
+	assert(e->e_u.e_elf.e_nscn > 0);
+
+	if ((scn = _libelf_allocate_scn(e, e->e_u.e_elf.e_nscn)) == NULL)
+		return (NULL);
+
+	e->e_u.e_elf.e_nscn++;
+
+	(void) elf_flagscn(scn, ELF_C_SET, ELF_F_DIRTY);
+
+	return (scn);
+}
+
+Elf_Scn *
+elf_nextscn(Elf *e, Elf_Scn *s)
+{
+	if (e == NULL || (e->e_kind != ELF_K_ELF) ||
+	    (s && s->s_elf != e)) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	return (s == NULL ? elf_getscn(e, (size_t) 1) :
+	    STAILQ_NEXT(s, s_next));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_shnum.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <ar.h>
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: elf_shnum.c 3174 2015-03-27 17:13:41Z emaste $");
+
+static int
+_libelf_getshdrnum(Elf *e, size_t *shnum)
+{
+	void *eh;
+	int ec;
+
+	if (e == NULL || e->e_kind != ELF_K_ELF ||
+	    ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (-1);
+	}
+
+	if ((eh = _libelf_ehdr(e, ec, 0)) == NULL)
+		return (-1);
+
+	*shnum = e->e_u.e_elf.e_nscn;
+
+	return (0);
+}
+
+int
+elf_getshdrnum(Elf *e, size_t *shnum)
+{
+	return (_libelf_getshdrnum(e, shnum));
+}
+
+/* Deprecated API. */
+int
+elf_getshnum(Elf *e, size_t *shnum)
+{
+	return (_libelf_getshdrnum(e, shnum) >= 0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_shstrndx.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,80 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <ar.h>
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: elf_shstrndx.c 3174 2015-03-27 17:13:41Z emaste $");
+
+static int
+_libelf_getshdrstrndx(Elf *e, size_t *strndx)
+{
+	void *eh;
+	int ec;
+
+	if (e == NULL || e->e_kind != ELF_K_ELF ||
+	    ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (-1);
+	}
+
+	if ((eh = _libelf_ehdr(e, ec, 0)) == NULL)
+		return (-1);
+
+	*strndx = e->e_u.e_elf.e_strndx;
+
+	return (0);
+}
+
+int
+elf_getshdrstrndx(Elf *e, size_t *strndx)
+{
+	return (_libelf_getshdrstrndx(e, strndx));
+}
+
+int
+elf_getshstrndx(Elf *e, size_t *strndx)	/* Deprecated API. */
+{
+	return (_libelf_getshdrstrndx(e, strndx) >= 0);
+}
+
+int
+elf_setshstrndx(Elf *e, size_t strndx)
+{
+	void *eh;
+	int ec;
+
+	if (e == NULL || e->e_kind != ELF_K_ELF ||
+	    ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) ||
+	    ((eh = _libelf_ehdr(e, ec, 0)) == NULL)) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	return (_libelf_setshstrndx(e, eh, ec, strndx));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_strptr.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,116 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_strptr.3 1081 2010-08-14 02:23:48Z jkoshy $
+.\"
+.Dd December 16, 2006
+.Os
+.Dt ELF_STRPTR 3
+.Sh NAME
+.Nm elf_strptr
+.Nd retrieve a string pointer in a string table
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft "char *"
+.Fn elf_strptr "Elf *elf" "size_t scndx" "size_t stroffset"
+.Sh DESCRIPTION
+Function
+.Fn elf_strptr
+allows an application to convert a string table offset to a string
+pointer, correctly translating the offset in the presence
+of multiple
+.Vt Elf_Data
+descriptors covering the contents of the section.
+.Pp
+Argument
+.Ar elf
+is a descriptor for an ELF object.
+Argument
+.Ar scndx
+is the section index for an ELF string table.
+Argument
+.Ar stroffset
+is the index of the desired string in the string
+table.
+.Sh RETURN VALUES
+Function
+.Fn elf_strptr
+returns a valid pointer on success or NULL in case an error was
+encountered.
+.Sh ERRORS
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was NULL
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was not a descriptor for an ELF object.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar scndx
+was not the section index for a string table.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar stroffset
+exceeded the size of the string table.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar stroffset
+index an unallocated region of the string table.
+.It Bq Er ELF_E_DATA
+Offset
+.Ar stroffset
+indexed a region that was not covered by any Elf_Data
+descriptor.
+.It Bq Er ELF_E_DATA
+An erroneous
+.Vt Elf_Data
+descriptor was part of the section specified by argument
+.Ar scndx .
+.It Bq Er ELF_E_HEADER
+ELF descriptor
+.Ar elf
+contained an invalid section header.
+.It Bq Er ELF_E_RESOURCE
+An out of memory condition was detected.
+.It Bq Er ELF_E_SECTION
+Section
+.Ar scndx
+contained a malformed section header.
+.It Bq Er ELF_E_SECTION
+The ELF descriptor in argument
+.Ar elf
+did not adhere to the conventions used for extended numbering.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf32_getshdr 3 ,
+.Xr elf64_getshdr 3 ,
+.Xr elf_getdata 3 ,
+.Xr elf_rawdata 3 ,
+.Xr gelf 3 ,
+.Xr gelf_getshdr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_strptr.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,132 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+
+#include <assert.h>
+#include <gelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: elf_strptr.c 2990 2014-03-17 09:56:58Z jkoshy $");
+
+/*
+ * Convert an ELF section#,offset pair to a string pointer.
+ */
+
+char *
+elf_strptr(Elf *e, size_t scndx, size_t offset)
+{
+	Elf_Scn *s;
+	Elf_Data *d;
+	GElf_Shdr shdr;
+	uint64_t alignment, count;
+
+	if (e == NULL || e->e_kind != ELF_K_ELF) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	if ((s = elf_getscn(e, scndx)) == NULL ||
+	    gelf_getshdr(s, &shdr) == NULL)
+		return (NULL);
+
+	if (shdr.sh_type != SHT_STRTAB ||
+	    offset >= shdr.sh_size) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	d = NULL;
+	if (e->e_flags & ELF_F_LAYOUT) {
+
+		/*
+		 * The application is taking responsibility for the
+		 * ELF object's layout, so we can directly translate
+		 * an offset to a `char *' address using the `d_off'
+		 * members of Elf_Data descriptors.
+		 */
+		while ((d = elf_getdata(s, d)) != NULL) {
+
+			if (d->d_buf == 0 || d->d_size == 0)
+				continue;
+
+			if (d->d_type != ELF_T_BYTE) {
+				LIBELF_SET_ERROR(DATA, 0);
+				return (NULL);
+			}
+
+			if (offset >= d->d_off &&
+			    offset < d->d_off + d->d_size)
+				return ((char *) d->d_buf + offset - d->d_off);
+		}
+	} else {
+		/*
+		 * Otherwise, the `d_off' members are not useable and
+		 * we need to compute offsets ourselves, taking into
+		 * account 'holes' in coverage of the section introduced
+		 * by alignment requirements.
+		 */
+		count = (uint64_t) 0;	/* cumulative count of bytes seen */
+		while ((d = elf_getdata(s, d)) != NULL && count <= offset) {
+
+			if (d->d_buf == NULL || d->d_size == 0)
+				continue;
+
+			if (d->d_type != ELF_T_BYTE) {
+				LIBELF_SET_ERROR(DATA, 0);
+				return (NULL);
+			}
+
+			if ((alignment = d->d_align) > 1) {
+				if ((alignment & (alignment - 1)) != 0) {
+					LIBELF_SET_ERROR(DATA, 0);
+					return (NULL);
+				}
+				count = roundup2(count, alignment);
+			}
+
+			if (offset < count) {
+				/* offset starts in the 'hole' */
+				LIBELF_SET_ERROR(ARGUMENT, 0);
+				return (NULL);
+			}
+
+			if (offset < count + d->d_size) {
+				if (d->d_buf != NULL)
+					return ((char *) d->d_buf +
+					    offset - count);
+				LIBELF_SET_ERROR(DATA, 0);
+				return (NULL);
+			}
+
+			count += d->d_size;
+		}
+	}
+
+	LIBELF_SET_ERROR(ARGUMENT, 0);
+	return (NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_types.m4	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,309 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: elf_types.m4 321 2009-03-07 16:59:14Z jkoshy $
+ */
+
+/*
+ * ELF types, defined in the "enum Elf_Type" API.
+ *
+ * The members of the list form a 2-tuple: (name, C-type-suffix).
+ * + `name' is an Elf_Type symbol without the `ELF_T_' prefix.
+ * + `C-type-suffix' is the suffix for Elf32_ and Elf64_ type names.
+ */
+
+define(`ELF_TYPE_LIST',
+	``ADDR,		Addr',
+	`BYTE,		Byte',
+	`CAP,		Cap',
+	`DYN,		Dyn',
+	`EHDR,		Ehdr',
+	`GNUHASH,	-',
+	`HALF,		Half',
+	`LWORD,		Lword',
+	`MOVE,		Move',
+	`MOVEP,		MoveP',
+	`NOTE,		Note',
+	`OFF,		Off',
+	`PHDR,		Phdr',
+	`REL,		Rel',
+	`RELA,		Rela',
+	`SHDR,		Shdr',
+	`SWORD,		Sword',
+	`SXWORD,	Sxword',
+	`SYMINFO,	Syminfo',
+	`SYM,		Sym',
+	`VDEF,		Verdef',
+	`VNEED,		Verneed',
+	`WORD,		Word',
+	`XWORD,		Xword',
+	`NUM,		_'')
+
+/*
+ * DEFINE_STRUCT(NAME,MEMBERLIST...)
+ *
+ * Map a type name to its members.
+ *
+ * Each member-list element comprises of pairs of (field name, type),
+ * in the sequence used in the file representation of `NAME'.
+ *
+ * Each member list element comprises a pair containing a field name
+ * and a basic type.  Basic types include IDENT, HALF, WORD, LWORD,
+ * ADDR{32,64}, OFF{32,64}, SWORD, XWORD, SXWORD.
+ *
+ * The last element of a member list is the null element: `_,_'.
+ */
+
+define(`DEFINE_STRUCT',`define(`$1_DEF',shift($@))dnl')
+
+DEFINE_STRUCT(`Elf32_Cap',
+	``c_tag,	WORD',
+	`c_un.c_val,	WORD',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf64_Cap',
+	``c_tag,	XWORD',
+	`c_un.c_val,	XWORD',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf32_Dyn',
+	``d_tag,	SWORD',
+	`d_un.d_ptr,	WORD',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf64_Dyn',
+	``d_tag,	SXWORD',
+	`d_un.d_ptr,	XWORD',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf32_Ehdr',
+	``e_ident,	IDENT',
+	`e_type, 	HALF',
+	`e_machine,	HALF',
+	`e_version,	WORD',
+	`e_entry,	ADDR',
+	`e_phoff,	OFF',
+	`e_shoff,	OFF',
+	`e_flags,	WORD',
+	`e_ehsize,	HALF',
+	`e_phentsize,	HALF',
+	`e_phnum,	HALF',
+	`e_shentsize,	HALF',
+	`e_shnum,	HALF',
+	`e_shstrndx,	HALF',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf64_Ehdr',
+	``e_ident,	IDENT',
+	`e_type, 	HALF',
+	`e_machine,	HALF',
+	`e_version,	WORD',
+	`e_entry,	ADDR',
+	`e_phoff,	OFF',
+	`e_shoff,	OFF',
+	`e_flags,	WORD',
+	`e_ehsize,	HALF',
+	`e_phentsize,	HALF',
+	`e_phnum,	HALF',
+	`e_shentsize,	HALF',
+	`e_shnum,	HALF',
+	`e_shstrndx,	HALF',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf32_Move',
+	``m_value,	LWORD',
+	`m_info,	WORD',
+	`m_poffset,	WORD',
+	`m_repeat,	HALF',
+	`m_stride,	HALF',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf64_Move',
+	``m_value,	LWORD',
+	`m_info,	XWORD',
+	`m_poffset,	XWORD',
+	`m_repeat,	HALF',
+	`m_stride,	HALF',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf32_Phdr',
+	``p_type,	WORD',
+	`p_offset,	OFF',
+	`p_vaddr,	ADDR',
+	`p_paddr,	ADDR',
+	`p_filesz,	WORD',
+	`p_memsz,	WORD',
+	`p_flags,	WORD',
+	`p_align,	WORD',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf64_Phdr',
+	``p_type,	WORD',
+	`p_flags,	WORD',
+	`p_offset,	OFF',
+	`p_vaddr,	ADDR',
+	`p_paddr,	ADDR',
+	`p_filesz,	XWORD',
+	`p_memsz,	XWORD',
+	`p_align,	XWORD',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf32_Rel',
+	``r_offset,	ADDR',
+	`r_info,	WORD',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf64_Rel',
+	``r_offset,	ADDR',
+	`r_info,	XWORD',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf32_Rela',
+	``r_offset,	ADDR',
+	`r_info,	WORD',
+	`r_addend,	SWORD',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf64_Rela',
+	``r_offset,	ADDR',
+	`r_info,	XWORD',
+	`r_addend,	SXWORD',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf32_Shdr',
+	``sh_name,	WORD',
+	`sh_type,	WORD',
+	`sh_flags,	WORD',
+	`sh_addr,	ADDR',
+	`sh_offset,	OFF',
+	`sh_size,	WORD',
+	`sh_link,	WORD',
+	`sh_info,	WORD',
+	`sh_addralign,	WORD',
+	`sh_entsize,	WORD',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf64_Shdr',
+	``sh_name,	WORD',
+	`sh_type,	WORD',
+	`sh_flags,	XWORD',
+	`sh_addr,	ADDR',
+	`sh_offset,	OFF',
+	`sh_size,	XWORD',
+	`sh_link,	WORD',
+	`sh_info,	WORD',
+	`sh_addralign,	XWORD',
+	`sh_entsize,	XWORD',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf32_Sym',
+	``st_name,	WORD',
+	`st_value,	ADDR',
+	`st_size,	WORD',
+	`st_info,	BYTE',
+	`st_other,	BYTE',
+	`st_shndx,	HALF',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf64_Sym',
+	``st_name,	WORD',
+	`st_info,	BYTE',
+	`st_other,	BYTE',
+	`st_shndx,	HALF',
+	`st_value,	ADDR',
+	`st_size,	XWORD',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf32_Syminfo',
+	``si_boundto,	HALF',
+	`si_flags,	HALF',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf64_Syminfo',
+	``si_boundto,	HALF',
+	`si_flags,	HALF',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf32_Verdaux',
+	``vda_name,	WORD',
+	`vda_next,	WORD',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf64_Verdaux',
+	``vda_name,	WORD',
+	`vda_next,	WORD',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf32_Verdef',
+	``vd_version,	HALF',
+	`vd_flags,	HALF',
+	`vd_ndx,	HALF',
+	`vd_cnt,	HALF',
+	`vd_hash,	WORD',
+	`vd_aux,	WORD',
+	`vd_next,	WORD',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf64_Verdef',
+	``vd_version,	HALF',
+	`vd_flags,	HALF',
+	`vd_ndx,	HALF',
+	`vd_cnt,	HALF',
+	`vd_hash,	WORD',
+	`vd_aux,	WORD',
+	`vd_next,	WORD',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf32_Verneed',
+	``vn_version,	HALF',
+	`vn_cnt,	HALF',
+	`vn_file,	WORD',
+	`vn_aux,	WORD',
+	`vn_next,	WORD',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf64_Verneed',
+	``vn_version,	HALF',
+	`vn_cnt,	HALF',
+	`vn_file,	WORD',
+	`vn_aux,	WORD',
+	`vn_next,	WORD',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf32_Vernaux',
+	``vna_hash,	WORD',
+	`vna_flags,	HALF',
+	`vna_other,	HALF',
+	`vna_name,	WORD',
+	`vna_next,	WORD',
+	`_,_'')
+
+DEFINE_STRUCT(`Elf64_Vernaux',
+	``vna_hash,	WORD',
+	`vna_flags,	HALF',
+	`vna_other,	HALF',
+	`vna_name,	WORD',
+	`vna_next,	WORD',
+	`_,_'')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_update.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,378 @@
+.\" Copyright (c) 2006-2011 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_update.3 1729 2011-08-14 09:13:00Z jkoshy $
+.\"
+.Dd August 14, 2011
+.Os
+.Dt ELF_UPDATE 3
+.Sh NAME
+.Nm elf_update
+.Nd update an ELF descriptor
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft off_t
+.Fn elf_update "Elf *elf" "Elf_Cmd cmd"
+.Sh DESCRIPTION
+Function
+.Fn elf_update
+causes the library to recalculate the structure of an ELF
+object and optionally write out the image of the object
+to file.
+.Pp
+Argument
+.Ar elf
+should reference a valid ELF descriptor.
+.Pp
+Argument
+.Ar cmd
+can be one of the following values:
+.Bl -tag -width "Dv ELF_C_WRITE"
+.It Dv ELF_C_NULL
+The library will recalculate structural information flagging
+modified structures with the
+.Dv ELF_F_DIRTY
+flag, but will not write data to the underlying file image.
+.It Dv ELF_C_WRITE
+The library will recalculate structural information and will
+also write the new image to the underlying file.
+The ELF descriptor referenced by argument
+.Ar elf
+should permit the underlying ELF object to be written or updated
+(see
+.Xr elf_begin 3 ) .
+.El
+.Pp
+All pointers to
+.Vt Elf_Scn
+and
+.Vt Elf_Data
+descriptors associated with descriptor
+.Ar elf
+should be considered invalid after a call to
+.Fn elf_update .
+.Ss Specifying Object Layout
+The
+.Lb libelf
+supports two layout modes.
+.Bl -tag -width indent
+.It "Library Layout"
+If the
+.Dv ELF_F_LAYOUT
+flag is not set on the ELF descriptor, the ELF library will lay out
+the ELF object according to the following scheme:
+.Bl -tag -compact -width "Section Data"
+.It Em EHDR
+The ELF executable header will be placed at the start of the object.
+.It Em PHDR
+If the ELF descriptor contains a program header table, it will be
+placed after the Executable Header.
+.It Em Section Data
+ELF section data, if any, will be placed next, keeping each section's
+alignment requirements in mind.
+.It Em SHDR
+The ELF section header table, if any, will be placed last.
+.El
+.It "Application Controlled Layout"
+The application can take full control of the layout of the ELF object
+by setting the
+.Dv ELF_F_LAYOUT
+flag on the ELF descriptor (see
+.Xr elf_flagelf 3 ) .
+In this case the library will lay out the ELF object using
+application-supplied information as below:
+.Pp
+.Bl -tag -compact -width "Section Data"
+.It Em EHDR
+The ELF executable header will be placed at the start of the object.
+.It Em PHDR
+The ELF program header table, if any, it will be placed at the offset
+specified in the
+.Va e_phoff
+field of the ELF executable header.
+.It Em Section Data
+The data for each ELF section will be placed at the offset specified
+by the
+.Va sh_offset
+field of the section's header.
+The size of the section will be taken from the
+.Va sh_size
+field of the section header.
+.It Em SHDR
+The ELF section header table, if any, will be placed at the offset
+specified by the
+.Va e_shoff
+field of the executable header.
+.El
+.El
+.Pp
+Gaps in the coverage of the file's contents will be set to the fill value
+specified by
+.Xr elf_fill 3 .
+.Ss Application Supplied Information
+The application needs to set the following fields in the data
+structures associated with the ELF descriptor prior to calling
+.Fn elf_update .
+.Bl -tag -width indent
+.It "Executable Header"
+The fields of the ELF executable header that need to be set by the
+application are:
+.Pp
+.Bl -tag -width "e_ident[EI_OSABI]" -compact
+.It Va e_entry
+To be set to the desired entry address for executables.
+.It Va e_flags
+To be set to the desired processor specific flags.
+.It Va "e_ident[EI_DATA]"
+Must be set to one of
+.Dv ELFDATA2LSB
+or
+.Dv ELFDATA2MSB .
+.It Va "e_ident[EI_OSABI]"
+To be set to the OS ABI desired.
+For example, for
+.Fx
+executables, this field should be set to
+.Dv ELFOSABI_FREEBSD .
+.It Va e_machine
+To be set to the desired machine architecture, one of the
+.Dv EM_*
+values in the header file
+.In elfdefinitions.h .
+.It Va e_phoff
+If the application is managing the object's layout, it must
+set this field to the file offset of the ELF program header table.
+.It Va e_shoff
+If the application is managing the object's layout, it must
+set this field to the file offset of the ELF section header table.
+.It Va e_shstrndx
+To be set to the index of the string table containing
+section names.
+.It Va e_type
+To be set to the type of the ELF object, one of the
+.Dv ET_*
+values in the header file
+.In elfdefinitions.h .
+.It Va e_version
+To be set to the desired version of the ELF object.
+.El
+.It "Program Header"
+All fields of the entries in the program header table need to be
+set by the application.
+.It "Section Header"
+The fields of ELF section headers that need to be set by the
+application are:
+.Pp
+.Bl -tag -width "sh_addralign" -compact
+.It Va sh_addr
+To be set to the memory address where the section should reside.
+.It Va sh_addralign
+If the application is managing the file layout, it must set this
+field to the desired alignment for the section's contents.
+This value must be a power of two and must be at least as large as the
+largest alignment needed by any
+.Vt Elf_Data
+descriptor associated with the section.
+.It Va sh_entsize
+To be set to the size of each entry, for sections containing fixed size
+elements, or set to zero for sections without fixed size elements.
+If the application is not managing file layout, it may leave this
+field as zero for those sections whose types are known to the library.
+.It Va sh_flags
+To be set to the desired section flags.
+.It Va sh_info
+To be set as described in
+.Xr elf 5 .
+.It Va sh_link
+To be set as described in
+.Xr elf 5 .
+.It Va sh_name
+To be set to the index of the section's name in the string table
+containing section names.
+.It Va sh_offset
+If the application is managing the file layout, it must set this
+field to the file offset of the section's contents.
+.It Va sh_size
+If the application is managing the file layout, it must set this
+field to the file size of the section's contents.
+.It Va sh_type
+To be set to the type of the section.
+.El
+.It "Section Data"
+The
+.Vt Elf_Data
+descriptors associated with each section specify its contents
+(see
+.Xr elf_getdata 3 ) .
+While all the fields in these descriptors are under application
+control, the following fields influence object layout:
+.Bl -tag -width "Va d_align" -compact
+.It Va d_align
+To be set to the desired alignment, within the containing section, of
+the descriptor's data.
+.It Va d_off
+If the application is managing object layout, it must set this field
+to the file offset, within the section, at which the descriptor's data
+should be placed.
+.It Va d_size
+To be set to the size in bytes of the memory representation of the
+descriptor's data.
+.El
+.El
+.Sh RETURN VALUES
+Function
+.Fn elf_update
+returns the total size of the file image if successful, or -1 if an
+error occurred.
+.Sh ERRORS
+This function may fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was null.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar cmd
+was not recognized.
+.It Bq Er ELF_E_ARGUMENT
+The argument
+.Ar elf
+was not a descriptor for an ELF object.
+.It Bq Er ELF_E_CLASS
+The
+.Va e_ident[EI_CLASS]
+field of the executable header of argument
+.Ar elf
+did not match the class of the file.
+.It Bq Er ELF_E_DATA
+An
+.Vt Elf_Data
+descriptor contained in argument
+.Ar elf
+specified an unsupported type.
+.It Bq Er ELF_E_DATA
+An
+.Vt Elf_Data
+descriptor specified an alignment that was zero or was not a power of
+two.
+.It Bq Er ELF_E_HEADER
+The ELF header in argument
+.Ar elf
+requested a different byte order from the byte order already
+associated with the file.
+.It Bq Er ELF_E_IO
+An I/O error was encountered.
+.It Bq Er ELF_E_LAYOUT
+An
+.Vt Elf_Data
+descriptor contained in argument
+.Ar elf
+specified an alignment incompatible with its containing section.
+.It Bq Er ELF_E_LAYOUT
+Argument
+.Ar elf
+contained section descriptors that overlapped in extent.
+.It Bq Er ELF_E_LAYOUT
+Argument
+.Ar elf
+contained section descriptors that were incorrectly aligned or were
+too small for their data.
+.It Bq Er ELF_E_LAYOUT
+The flag
+.Dv ELF_F_LAYOUT
+was set on the Elf descriptor and the executable header overlapped
+with the program header table.
+.It Bq Er ELF_E_LAYOUT
+The flag
+.Dv ELF_F_LAYOUT
+was set on the Elf descriptor and the program header table was placed
+at a misaligned file offset.
+.It Bq Er ELF_E_LAYOUT
+The flag
+.Dv ELF_F_LAYOUT
+was set on the Elf descriptor and the section header table overlapped
+an extent mapped by a section descriptor.
+.It Bq Er ELF_E_LAYOUT
+The
+.Dv ELF_F_LAYOUT
+flag was set on the Elf descriptor, and the
+.Va d_offset
+field in an
+.Vt Elf_Data
+descriptor contained a value that was not a multiple of the
+descriptor's specified alignment.
+.It Bq Er ELF_E_MODE
+An
+.Dv ELF_C_WRITE
+operation was requested with an ELF descriptor that was not opened for
+writing or updating.
+.It Bq Er ELF_E_SECTION
+Argument
+.Ar elf
+contained a section with an unrecognized type.
+.It Bq Er ELF_E_SECTION
+The section header at index
+.Dv SHN_UNDEF
+had an illegal section type.
+.It Bq Er ELF_E_SEQUENCE
+An
+.Dv ELF_C_WRITE
+operation was requested after a prior call to
+.Fn elf_cntl elf ELF_C_FDDONE
+disassociated the ELF descriptor
+.Ar elf
+from its underlying file.
+.It Bq Er ELF_E_VERSION
+Argument
+.Ar elf
+had an unsupported version or contained an
+.Vt Elf_Data
+descriptor with an unsupported version.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf32_getehdr 3 ,
+.Xr elf32_getphdr 3 ,
+.Xr elf32_newehdr 3 ,
+.Xr elf32_newphdr 3 ,
+.Xr elf64_getehdr 3 ,
+.Xr elf64_getphdr 3 ,
+.Xr elf64_newehdr 3 ,
+.Xr elf64_newphdr 3 ,
+.Xr elf_begin 3 ,
+.Xr elf_cntl 3 ,
+.Xr elf_fill 3 ,
+.Xr elf_flagehdr 3 ,
+.Xr elf_flagelf 3 ,
+.Xr elf_getdata 3 ,
+.Xr elf_getscn 3 ,
+.Xr elf_newdata 3 ,
+.Xr elf_newscn 3 ,
+.Xr elf_rawdata 3 ,
+.Xr gelf 3 ,
+.Xr gelf_newehdr 3 ,
+.Xr gelf_newphdr 3 ,
+.Xr elf 5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_update.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,1217 @@
+/*-
+ * Copyright (c) 2006-2011 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <gelf.h>
+#include <libelf.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "_libelf.h"
+
+#if	ELFTC_HAVE_MMAP
+#include <sys/mman.h>
+#endif
+
+ELFTC_VCSID("$Id: elf_update.c 3190 2015-05-04 15:23:08Z jkoshy $");
+
+/*
+ * Layout strategy:
+ *
+ * - Case 1: ELF_F_LAYOUT is asserted
+ *     In this case the application has full control over where the
+ *     section header table, program header table, and section data
+ *     will reside.   The library only perform error checks.
+ *
+ * - Case 2: ELF_F_LAYOUT is not asserted
+ *
+ *     The library will do the object layout using the following
+ *     ordering:
+ *     - The executable header is placed first, are required by the
+ *     	 ELF specification.
+ *     - The program header table is placed immediately following the
+ *       executable header.
+ *     - Section data, if any, is placed after the program header
+ *       table, aligned appropriately.
+ *     - The section header table, if needed, is placed last.
+ *
+ *     There are two sub-cases to be taken care of:
+ *
+ *     - Case 2a: e->e_cmd == ELF_C_READ or ELF_C_RDWR
+ *
+ *       In this sub-case, the underlying ELF object may already have
+ *       content in it, which the application may have modified.  The
+ *       library will retrieve content from the existing object as
+ *       needed.
+ *
+ *     - Case 2b: e->e_cmd == ELF_C_WRITE
+ *
+ *       The ELF object is being created afresh in this sub-case;
+ *       there is no pre-existing content in the underlying ELF
+ *       object.
+ */
+
+/*
+ * The types of extents in an ELF object.
+ */
+enum elf_extent {
+	ELF_EXTENT_EHDR,
+	ELF_EXTENT_PHDR,
+	ELF_EXTENT_SECTION,
+	ELF_EXTENT_SHDR
+};
+
+/*
+ * A extent descriptor, used when laying out an ELF object.
+ */
+struct _Elf_Extent {
+	SLIST_ENTRY(_Elf_Extent) ex_next;
+	uint64_t	ex_start; /* Start of the region. */
+	uint64_t	ex_size;  /* The size of the region. */
+	enum elf_extent	ex_type;  /* Type of region. */
+	void		*ex_desc; /* Associated descriptor. */
+};
+
+SLIST_HEAD(_Elf_Extent_List, _Elf_Extent);
+
+/*
+ * Compute the extents of a section, by looking at the data
+ * descriptors associated with it.  The function returns 1
+ * if successful, or zero if an error was detected.
+ */
+static int
+_libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t rc)
+{
+	Elf_Data *d;
+	size_t fsz, msz;
+	int ec, elftype;
+	uint32_t sh_type;
+	uint64_t d_align;
+	Elf32_Shdr *shdr32;
+	Elf64_Shdr *shdr64;
+	struct _Libelf_Data *ld;
+	uint64_t scn_size, scn_alignment;
+	uint64_t sh_align, sh_entsize, sh_offset, sh_size;
+
+	ec = e->e_class;
+
+	shdr32 = &s->s_shdr.s_shdr32;
+	shdr64 = &s->s_shdr.s_shdr64;
+	if (ec == ELFCLASS32) {
+		sh_type    = shdr32->sh_type;
+		sh_align   = (uint64_t) shdr32->sh_addralign;
+		sh_entsize = (uint64_t) shdr32->sh_entsize;
+		sh_offset  = (uint64_t) shdr32->sh_offset;
+		sh_size    = (uint64_t) shdr32->sh_size;
+	} else {
+		sh_type    = shdr64->sh_type;
+		sh_align   = shdr64->sh_addralign;
+		sh_entsize = shdr64->sh_entsize;
+		sh_offset  = shdr64->sh_offset;
+		sh_size    = shdr64->sh_size;
+	}
+
+	assert(sh_type != SHT_NULL && sh_type != SHT_NOBITS);
+
+	elftype = _libelf_xlate_shtype(sh_type);
+	if (elftype > ELF_T_LAST) {
+		LIBELF_SET_ERROR(SECTION, 0);
+		return (0);
+	}
+
+	if (sh_align == 0)
+		sh_align = _libelf_falign(elftype, ec);
+
+	/*
+	 * Compute the section's size and alignment using the data
+	 * descriptors associated with the section.
+	 */
+	if (STAILQ_EMPTY(&s->s_data)) {
+		/*
+		 * The section's content (if any) has not been read in
+		 * yet.  If section is not dirty marked dirty, we can
+		 * reuse the values in the 'sh_size' and 'sh_offset'
+		 * fields of the section header.
+		 */
+		if ((s->s_flags & ELF_F_DIRTY) == 0) {
+			/*
+			 * If the library is doing the layout, then we
+			 * compute the new start offset for the
+			 * section based on the current offset and the
+			 * section's alignment needs.
+			 *
+			 * If the application is doing the layout, we
+			 * can use the value in the 'sh_offset' field
+			 * in the section header directly.
+			 */
+			if (e->e_flags & ELF_F_LAYOUT)
+				goto updatedescriptor;
+			else
+				goto computeoffset;
+		}
+
+		/*
+		 * Otherwise, we need to bring in the section's data
+		 * from the underlying ELF object.
+		 */
+		if (e->e_cmd != ELF_C_WRITE && elf_getdata(s, NULL) == NULL)
+			return (0);
+	}
+
+	/*
+	 * Loop through the section's data descriptors.
+	 */
+	scn_size = 0L;
+	scn_alignment = 0;
+	STAILQ_FOREACH(ld, &s->s_data, d_next)  {
+
+		d = &ld->d_data;
+
+		/*
+		 * The data buffer's type is known.
+		 */
+		if (d->d_type >= ELF_T_NUM) {
+			LIBELF_SET_ERROR(DATA, 0);
+			return (0);
+		}
+
+		/*
+		 * The data buffer's version is supported.
+		 */
+		if (d->d_version != e->e_version) {
+			LIBELF_SET_ERROR(VERSION, 0);
+			return (0);
+		}
+
+		/*
+		 * The buffer's alignment is non-zero and a power of
+		 * two.
+		 */
+		if ((d_align = d->d_align) == 0 ||
+		    (d_align & (d_align - 1))) {
+			LIBELF_SET_ERROR(DATA, 0);
+			return (0);
+		}
+
+		/*
+		 * The buffer's size should be a multiple of the
+		 * memory size of the underlying type.
+		 */
+		msz = _libelf_msize(d->d_type, ec, e->e_version);
+		if (d->d_size % msz) {
+			LIBELF_SET_ERROR(DATA, 0);
+			return (0);
+		}
+
+		/*
+		 * If the application is controlling layout, then the
+		 * d_offset field should be compatible with the
+		 * buffer's specified alignment.
+		 */
+		if ((e->e_flags & ELF_F_LAYOUT) &&
+		    (d->d_off & (d_align - 1))) {
+			LIBELF_SET_ERROR(LAYOUT, 0);
+			return (0);
+		}
+
+		/*
+		 * Compute the section's size.
+		 */
+		if (e->e_flags & ELF_F_LAYOUT) {
+			if ((uint64_t) d->d_off + d->d_size > scn_size)
+				scn_size = d->d_off + d->d_size;
+		} else {
+			scn_size = roundup2(scn_size, d->d_align);
+			d->d_off = scn_size;
+			fsz = _libelf_fsize(d->d_type, ec, d->d_version,
+			    (size_t) d->d_size / msz);
+			scn_size += fsz;
+		}
+
+		/*
+		 * The section's alignment is the maximum alignment
+		 * needed for its data buffers.
+		 */
+		if (d_align > scn_alignment)
+			scn_alignment = d_align;
+	}
+
+
+	/*
+	 * If the application is requesting full control over the
+	 * layout of the section, check the section's specified size,
+	 * offsets and alignment for sanity.
+	 */
+	if (e->e_flags & ELF_F_LAYOUT) {
+		if (scn_alignment > sh_align ||
+		    sh_offset % sh_align ||
+		    sh_size < scn_size ||
+		    sh_offset % _libelf_falign(elftype, ec)) {
+			LIBELF_SET_ERROR(LAYOUT, 0);
+			return (0);
+		}
+		goto updatedescriptor;
+	}
+
+	/*
+	 * Otherwise, compute the values in the section header.
+	 *
+	 * The section alignment is the maximum alignment for any of
+	 * its contained data descriptors.
+	 */
+	if (scn_alignment > sh_align)
+		sh_align = scn_alignment;
+
+	/*
+	 * If the section entry size is zero, try and fill in an
+	 * appropriate entry size.  Per the elf(5) manual page
+	 * sections without fixed-size entries should have their
+	 * 'sh_entsize' field set to zero.
+	 */
+	if (sh_entsize == 0 &&
+	    (sh_entsize = _libelf_fsize(elftype, ec, e->e_version,
+		(size_t) 1)) == 1)
+		sh_entsize = 0;
+
+	sh_size = scn_size;
+
+computeoffset:
+	/*
+	 * Compute the new offset for the section based on
+	 * the section's alignment needs.
+	 */
+	sh_offset = roundup((uint64_t) rc, sh_align);
+
+	/*
+	 * Update the section header.
+	 */
+	if (ec == ELFCLASS32) {
+		shdr32->sh_addralign = (uint32_t) sh_align;
+		shdr32->sh_entsize   = (uint32_t) sh_entsize;
+		shdr32->sh_offset    = (uint32_t) sh_offset;
+		shdr32->sh_size      = (uint32_t) sh_size;
+	} else {
+		shdr64->sh_addralign = sh_align;
+		shdr64->sh_entsize   = sh_entsize;
+		shdr64->sh_offset    = sh_offset;
+		shdr64->sh_size      = sh_size;
+	}
+
+updatedescriptor:
+	/*
+	 * Update the section descriptor.
+	 */
+	s->s_size = sh_size;
+	s->s_offset = sh_offset;
+
+	return (1);
+}
+
+/*
+ * Free a list of extent descriptors.
+ */
+
+static void
+_libelf_release_extents(struct _Elf_Extent_List *extents)
+{
+	struct _Elf_Extent *ex;
+
+	while ((ex = SLIST_FIRST(extents)) != NULL) {
+		SLIST_REMOVE_HEAD(extents, ex_next);
+		free(ex);
+	}
+}
+
+/*
+ * Check if an extent 's' defined by [start..start+size) is free.
+ * This routine assumes that the given extent list is sorted in order
+ * of ascending extent offsets.
+ */
+
+static int
+_libelf_extent_is_unused(struct _Elf_Extent_List *extents,
+    const uint64_t start, const uint64_t size, struct _Elf_Extent **prevt)
+{
+	uint64_t tmax, tmin;
+	struct _Elf_Extent *t, *pt;
+	const uint64_t smax = start + size;
+
+	/* First, look for overlaps with existing extents. */
+	pt = NULL;
+	SLIST_FOREACH(t, extents, ex_next) {
+		tmin = t->ex_start;
+		tmax = tmin + t->ex_size;
+
+		if (tmax <= start) {
+			/*
+			 * 't' lies entirely before 's': ...| t |...| s |...
+			 */
+			pt = t;
+			continue;
+		} else if (smax <= tmin) {
+			/*
+			 * 's' lies entirely before 't', and after 'pt':
+			 *      ...| pt |...| s |...| t |...
+			 */
+			assert(pt == NULL ||
+			    pt->ex_start + pt->ex_size <= start);
+			break;
+		} else
+			/* 's' and 't' overlap. */
+			return (0);
+	}
+
+	if (prevt)
+		*prevt = pt;
+	return (1);
+}
+
+/*
+ * Insert an extent into the list of extents.
+ */
+
+static int
+_libelf_insert_extent(struct _Elf_Extent_List *extents, int type,
+    uint64_t start, uint64_t size, void *desc)
+{
+	struct _Elf_Extent *ex, *prevt;
+
+	assert(type >= ELF_EXTENT_EHDR && type <= ELF_EXTENT_SHDR);
+
+	prevt = NULL;
+
+	/*
+	 * If the requested range overlaps with an existing extent,
+	 * signal an error.
+	 */
+	if (!_libelf_extent_is_unused(extents, start, size, &prevt)) {
+		LIBELF_SET_ERROR(LAYOUT, 0);
+		return (0);
+	}
+
+	/* Allocate and fill in a new extent descriptor. */
+	if ((ex = malloc(sizeof(struct _Elf_Extent))) == NULL) {
+		LIBELF_SET_ERROR(RESOURCE, errno);
+		return (0);
+	}
+	ex->ex_start = start;
+	ex->ex_size = size;
+	ex->ex_desc = desc;
+	ex->ex_type = type;
+
+	/* Insert the region descriptor into the list. */
+	if (prevt)
+		SLIST_INSERT_AFTER(prevt, ex, ex_next);
+	else
+		SLIST_INSERT_HEAD(extents, ex, ex_next);
+	return (1);
+}
+
+/*
+ * Recompute section layout.
+ */
+
+static off_t
+_libelf_resync_sections(Elf *e, off_t rc, struct _Elf_Extent_List *extents)
+{
+	int ec;
+	Elf_Scn *s;
+	size_t sh_type;
+
+	ec = e->e_class;
+
+	/*
+	 * Make a pass through sections, computing the extent of each
+	 * section.
+	 */
+	STAILQ_FOREACH(s, &e->e_u.e_elf.e_scn, s_next) {
+		if (ec == ELFCLASS32)
+			sh_type = s->s_shdr.s_shdr32.sh_type;
+		else
+			sh_type = s->s_shdr.s_shdr64.sh_type;
+
+		if (sh_type == SHT_NOBITS || sh_type == SHT_NULL)
+			continue;
+
+		if (_libelf_compute_section_extents(e, s, rc) == 0)
+			return ((off_t) -1);
+
+		if (s->s_size == 0)
+			continue;
+
+		if (!_libelf_insert_extent(extents, ELF_EXTENT_SECTION,
+		    s->s_offset, s->s_size, s))
+			return ((off_t) -1);
+
+		if ((size_t) rc < s->s_offset + s->s_size)
+			rc = (off_t) (s->s_offset + s->s_size);
+	}
+
+	return (rc);
+}
+
+/*
+ * Recompute the layout of the ELF object and update the internal data
+ * structures associated with the ELF descriptor.
+ *
+ * Returns the size in bytes the ELF object would occupy in its file
+ * representation.
+ *
+ * After a successful call to this function, the following structures
+ * are updated:
+ *
+ * - The ELF header is updated.
+ * - All extents in the ELF object are sorted in order of ascending
+ *   addresses.  Sections have their section header table entries
+ *   updated.  An error is signalled if an overlap was detected among
+ *   extents.
+ * - Data descriptors associated with sections are checked for valid
+ *   types, offsets and alignment.
+ *
+ * After a resync_elf() successfully returns, the ELF descriptor is
+ * ready for being handed over to _libelf_write_elf().
+ */
+
+static off_t
+_libelf_resync_elf(Elf *e, struct _Elf_Extent_List *extents)
+{
+	int ec, eh_class;
+	unsigned int eh_byteorder, eh_version;
+	size_t align, fsz;
+	size_t phnum, shnum;
+	off_t rc, phoff, shoff;
+	void *ehdr, *phdr;
+	Elf32_Ehdr *eh32;
+	Elf64_Ehdr *eh64;
+
+	rc = 0;
+
+	ec = e->e_class;
+
+	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
+
+	/*
+	 * Prepare the EHDR.
+	 */
+	if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL)
+		return ((off_t) -1);
+
+	eh32 = ehdr;
+	eh64 = ehdr;
+
+	if (ec == ELFCLASS32) {
+		eh_byteorder = eh32->e_ident[EI_DATA];
+		eh_class     = eh32->e_ident[EI_CLASS];
+		phoff        = (off_t) eh32->e_phoff;
+		shoff        = (off_t) eh32->e_shoff;
+		eh_version   = eh32->e_version;
+	} else {
+		eh_byteorder = eh64->e_ident[EI_DATA];
+		eh_class     = eh64->e_ident[EI_CLASS];
+		phoff        = (off_t) eh64->e_phoff;
+		shoff        = (off_t) eh64->e_shoff;
+		eh_version   = eh64->e_version;
+	}
+
+	if (phoff < 0 || shoff < 0) {
+		LIBELF_SET_ERROR(HEADER, 0);
+		return ((off_t) -1);
+	}
+
+	if (eh_version == EV_NONE)
+		eh_version = EV_CURRENT;
+
+	if (eh_version != e->e_version) {	/* always EV_CURRENT */
+		LIBELF_SET_ERROR(VERSION, 0);
+		return ((off_t) -1);
+	}
+
+	if (eh_class != e->e_class) {
+		LIBELF_SET_ERROR(CLASS, 0);
+		return ((off_t) -1);
+	}
+
+	if (e->e_cmd != ELF_C_WRITE && eh_byteorder != e->e_byteorder) {
+		LIBELF_SET_ERROR(HEADER, 0);
+		return ((off_t) -1);
+	}
+
+	shnum = e->e_u.e_elf.e_nscn;
+	phnum = e->e_u.e_elf.e_nphdr;
+
+	e->e_byteorder = eh_byteorder;
+
+#define	INITIALIZE_EHDR(E,EC,V)	do {					\
+		unsigned int _version = (unsigned int) (V);		\
+		(E)->e_ident[EI_MAG0] = ELFMAG0;			\
+		(E)->e_ident[EI_MAG1] = ELFMAG1;			\
+		(E)->e_ident[EI_MAG2] = ELFMAG2;			\
+		(E)->e_ident[EI_MAG3] = ELFMAG3;			\
+		(E)->e_ident[EI_CLASS] = (unsigned char) (EC);		\
+		(E)->e_ident[EI_VERSION] = (_version & 0xFFU);		\
+		(E)->e_ehsize = (uint16_t) _libelf_fsize(ELF_T_EHDR,	\
+		    (EC), _version, (size_t) 1);			\
+		(E)->e_phentsize = (uint16_t) ((phnum == 0) ? 0 :	\
+		    _libelf_fsize(ELF_T_PHDR, (EC), _version,		\
+			(size_t) 1));					\
+		(E)->e_shentsize = (uint16_t) _libelf_fsize(ELF_T_SHDR,	\
+		    (EC), _version, (size_t) 1);			\
+	} while (0)
+
+	if (ec == ELFCLASS32)
+		INITIALIZE_EHDR(eh32, ec, eh_version);
+	else
+		INITIALIZE_EHDR(eh64, ec, eh_version);
+
+	(void) elf_flagehdr(e, ELF_C_SET, ELF_F_DIRTY);
+
+	rc += (off_t) _libelf_fsize(ELF_T_EHDR, ec, eh_version, (size_t) 1);
+
+	if (!_libelf_insert_extent(extents, ELF_EXTENT_EHDR, 0, (uint64_t) rc,
+		ehdr))
+		return ((off_t) -1);
+
+	/*
+	 * Compute the layout the program header table, if one is
+	 * present.  The program header table needs to be aligned to a
+	 * `natural' boundary.
+	 */
+	if (phnum) {
+		fsz = _libelf_fsize(ELF_T_PHDR, ec, eh_version, phnum);
+		align = _libelf_falign(ELF_T_PHDR, ec);
+
+		if (e->e_flags & ELF_F_LAYOUT) {
+			/*
+			 * Check offsets for sanity.
+			 */
+			if (rc > phoff) {
+				LIBELF_SET_ERROR(LAYOUT, 0);
+				return ((off_t) -1);
+			}
+
+			if (phoff % (off_t) align) {
+				LIBELF_SET_ERROR(LAYOUT, 0);
+				return ((off_t) -1);
+			}
+
+		} else
+			phoff = roundup(rc, (off_t) align);
+
+		rc = phoff + (off_t) fsz;
+
+		phdr = _libelf_getphdr(e, ec);
+
+		if (!_libelf_insert_extent(extents, ELF_EXTENT_PHDR,
+			(uint64_t) phoff, fsz, phdr))
+			return ((off_t) -1);
+	} else
+		phoff = 0;
+
+	/*
+	 * Compute the layout of the sections associated with the
+	 * file.
+	 */
+
+	if (e->e_cmd != ELF_C_WRITE &&
+	    (e->e_flags & LIBELF_F_SHDRS_LOADED) == 0 &&
+	    _libelf_load_section_headers(e, ehdr) == 0)
+		return ((off_t) -1);
+
+	if ((rc = _libelf_resync_sections(e, rc, extents)) < 0)
+		return ((off_t) -1);
+
+	/*
+	 * Compute the space taken up by the section header table, if
+	 * one is needed.
+	 *
+	 * If ELF_F_LAYOUT has been asserted, the application may have
+	 * placed the section header table in between existing
+	 * sections, so the net size of the file need not increase due
+	 * to the presence of the section header table.
+	 *
+	 * If the library is responsible for laying out the object,
+	 * the section header table is placed after section data.
+	 */
+	if (shnum) {
+		fsz = _libelf_fsize(ELF_T_SHDR, ec, eh_version, shnum);
+		align = _libelf_falign(ELF_T_SHDR, ec);
+
+		if (e->e_flags & ELF_F_LAYOUT) {
+			if (shoff % (off_t) align) {
+				LIBELF_SET_ERROR(LAYOUT, 0);
+				return ((off_t) -1);
+			}
+		} else
+			shoff = roundup(rc, (off_t) align);
+
+		if (shoff + (off_t) fsz > rc)
+			rc = shoff + (off_t) fsz;
+
+		if (!_libelf_insert_extent(extents, ELF_EXTENT_SHDR,
+			(uint64_t) shoff, fsz, NULL))
+			return ((off_t) -1);
+	} else
+		shoff = 0;
+
+	/*
+	 * Set the fields of the Executable Header that could potentially use
+	 * extended numbering.
+	 */
+	_libelf_setphnum(e, ehdr, ec, phnum);
+	_libelf_setshnum(e, ehdr, ec, shnum);
+
+	/*
+	 * Update the `e_phoff' and `e_shoff' fields if the library is
+	 * doing the layout.
+	 */
+	if ((e->e_flags & ELF_F_LAYOUT) == 0) {
+		if (ec == ELFCLASS32) {
+			eh32->e_phoff = (uint32_t) phoff;
+			eh32->e_shoff = (uint32_t) shoff;
+		} else {
+			eh64->e_phoff = (uint64_t) phoff;
+			eh64->e_shoff = (uint64_t) shoff;
+		}
+	}
+
+	return (rc);
+}
+
+/*
+ * Write out the contents of an ELF section.
+ */
+
+static off_t
+_libelf_write_scn(Elf *e, unsigned char *nf, struct _Elf_Extent *ex)
+{
+	int ec;
+	off_t rc;
+	Elf_Scn *s;
+	int elftype;
+	Elf_Data *d, dst;
+	uint32_t sh_type;
+	struct _Libelf_Data *ld;
+	uint64_t sh_off, sh_size;
+	size_t fsz, msz, nobjects;
+
+	assert(ex->ex_type == ELF_EXTENT_SECTION);
+
+	s = ex->ex_desc;
+	rc = (off_t) ex->ex_start;
+
+	if ((ec = e->e_class) == ELFCLASS32) {
+		sh_type = s->s_shdr.s_shdr32.sh_type;
+		sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size;
+	} else {
+		sh_type = s->s_shdr.s_shdr64.sh_type;
+		sh_size = s->s_shdr.s_shdr64.sh_size;
+	}
+
+	/*
+	 * Ignore sections that do not allocate space in the file.
+	 */
+	if (sh_type == SHT_NOBITS || sh_type == SHT_NULL || sh_size == 0)
+		return (rc);
+
+	elftype = _libelf_xlate_shtype(sh_type);
+	assert(elftype >= ELF_T_FIRST && elftype <= ELF_T_LAST);
+
+	sh_off = s->s_offset;
+	assert(sh_off % _libelf_falign(elftype, ec) == 0);
+
+	/*
+	 * If the section has a `rawdata' descriptor, and the section
+	 * contents have not been modified, use its contents directly.
+	 * The `s_rawoff' member contains the offset into the original
+	 * file, while `s_offset' contains its new location in the
+	 * destination.
+	 */
+
+	if (STAILQ_EMPTY(&s->s_data)) {
+
+		if ((d = elf_rawdata(s, NULL)) == NULL)
+			return ((off_t) -1);
+
+		STAILQ_FOREACH(ld, &s->s_rawdata, d_next) {
+
+			d = &ld->d_data;
+
+			if ((uint64_t) rc < sh_off + d->d_off)
+				(void) memset(nf + rc,
+				    LIBELF_PRIVATE(fillchar),
+				    (size_t) (sh_off + d->d_off -
+					(uint64_t) rc));
+			rc = (off_t) (sh_off + d->d_off);
+
+			assert(d->d_buf != NULL);
+			assert(d->d_type == ELF_T_BYTE);
+			assert(d->d_version == e->e_version);
+
+			(void) memcpy(nf + rc,
+			    e->e_rawfile + s->s_rawoff + d->d_off,
+			    (size_t) d->d_size);
+
+			rc += (off_t) d->d_size;
+		}
+
+		return (rc);
+	}
+
+	/*
+	 * Iterate over the set of data descriptors for this section.
+	 * The prior call to _libelf_resync_elf() would have setup the
+	 * descriptors for this step.
+	 */
+
+	dst.d_version = e->e_version;
+
+	STAILQ_FOREACH(ld, &s->s_data, d_next) {
+
+		d = &ld->d_data;
+
+		msz = _libelf_msize(d->d_type, ec, e->e_version);
+
+		if ((uint64_t) rc < sh_off + d->d_off)
+			(void) memset(nf + rc,
+			    LIBELF_PRIVATE(fillchar),
+			    (size_t) (sh_off + d->d_off - (uint64_t) rc));
+
+		rc = (off_t) (sh_off + d->d_off);
+
+		assert(d->d_buf != NULL);
+		assert(d->d_version == e->e_version);
+		assert(msz != 0);
+		assert(d->d_size % msz == 0);
+
+		nobjects = (size_t) (d->d_size / msz);
+
+		fsz = _libelf_fsize(d->d_type, ec, e->e_version, nobjects);
+
+		dst.d_buf    = nf + rc;
+		dst.d_size   = fsz;
+
+		if (_libelf_xlate(&dst, d, e->e_byteorder, ec, ELF_TOFILE) ==
+		    NULL)
+			return ((off_t) -1);
+
+		rc += (off_t) fsz;
+	}
+
+	return (rc);
+}
+
+/*
+ * Write out an ELF Executable Header.
+ */
+
+static off_t
+_libelf_write_ehdr(Elf *e, unsigned char *nf, struct _Elf_Extent *ex)
+{
+	int ec;
+	void *ehdr;
+	size_t fsz, msz;
+	Elf_Data dst, src;
+
+	assert(ex->ex_type == ELF_EXTENT_EHDR);
+	assert(ex->ex_start == 0); /* Ehdr always comes first. */
+
+	ec = e->e_class;
+
+	ehdr = _libelf_ehdr(e, ec, 0);
+	assert(ehdr != NULL);
+
+	fsz = _libelf_fsize(ELF_T_EHDR, ec, e->e_version, (size_t) 1);
+	msz = _libelf_msize(ELF_T_EHDR, ec, e->e_version);
+
+	(void) memset(&dst, 0, sizeof(dst));
+	(void) memset(&src, 0, sizeof(src));
+
+	src.d_buf     = ehdr;
+	src.d_size    = msz;
+	src.d_type    = ELF_T_EHDR;
+	src.d_version = dst.d_version = e->e_version;
+
+	dst.d_buf     = nf;
+	dst.d_size    = fsz;
+
+	if (_libelf_xlate(&dst, &src, e->e_byteorder, ec, ELF_TOFILE) ==
+	    NULL)
+		return ((off_t) -1);
+
+	return ((off_t) fsz);
+}
+
+/*
+ * Write out an ELF program header table.
+ */
+
+static off_t
+_libelf_write_phdr(Elf *e, unsigned char *nf, struct _Elf_Extent *ex)
+{
+	int ec;
+	void *ehdr;
+	Elf32_Ehdr *eh32;
+	Elf64_Ehdr *eh64;
+	Elf_Data dst, src;
+	size_t fsz, phnum;
+	uint64_t phoff;
+
+	assert(ex->ex_type == ELF_EXTENT_PHDR);
+
+	ec = e->e_class;
+	ehdr = _libelf_ehdr(e, ec, 0);
+	phnum = e->e_u.e_elf.e_nphdr;
+
+	assert(phnum > 0);
+
+	if (ec == ELFCLASS32) {
+		eh32 = (Elf32_Ehdr *) ehdr;
+		phoff = (uint64_t) eh32->e_phoff;
+	} else {
+		eh64 = (Elf64_Ehdr *) ehdr;
+		phoff = eh64->e_phoff;
+	}
+
+	assert(phoff > 0);
+	assert(ex->ex_start == phoff);
+	assert(phoff % _libelf_falign(ELF_T_PHDR, ec) == 0);
+
+	(void) memset(&dst, 0, sizeof(dst));
+	(void) memset(&src, 0, sizeof(src));
+
+	fsz = _libelf_fsize(ELF_T_PHDR, ec, e->e_version, phnum);
+	assert(fsz > 0);
+
+	src.d_buf = _libelf_getphdr(e, ec);
+	src.d_version = dst.d_version = e->e_version;
+	src.d_type = ELF_T_PHDR;
+	src.d_size = phnum * _libelf_msize(ELF_T_PHDR, ec,
+	    e->e_version);
+
+	dst.d_size = fsz;
+	dst.d_buf = nf + ex->ex_start;
+
+	if (_libelf_xlate(&dst, &src, e->e_byteorder, ec, ELF_TOFILE) ==
+	    NULL)
+		return ((off_t) -1);
+
+	return ((off_t) (phoff + fsz));
+}
+
+/*
+ * Write out an ELF section header table.
+ */
+
+static off_t
+_libelf_write_shdr(Elf *e, unsigned char *nf, struct _Elf_Extent *ex)
+{
+	int ec;
+	void *ehdr;
+	Elf_Scn *scn;
+	uint64_t shoff;
+	Elf32_Ehdr *eh32;
+	Elf64_Ehdr *eh64;
+	size_t fsz, nscn;
+	Elf_Data dst, src;
+
+	assert(ex->ex_type == ELF_EXTENT_SHDR);
+
+	ec = e->e_class;
+	ehdr = _libelf_ehdr(e, ec, 0);
+	nscn = e->e_u.e_elf.e_nscn;
+
+	if (ec == ELFCLASS32) {
+		eh32 = (Elf32_Ehdr *) ehdr;
+		shoff = (uint64_t) eh32->e_shoff;
+	} else {
+		eh64 = (Elf64_Ehdr *) ehdr;
+		shoff = eh64->e_shoff;
+	}
+
+	assert(nscn > 0);
+	assert(shoff % _libelf_falign(ELF_T_SHDR, ec) == 0);
+	assert(ex->ex_start == shoff);
+
+	(void) memset(&dst, 0, sizeof(dst));
+	(void) memset(&src, 0, sizeof(src));
+
+	src.d_type = ELF_T_SHDR;
+	src.d_size = _libelf_msize(ELF_T_SHDR, ec, e->e_version);
+	src.d_version = dst.d_version = e->e_version;
+
+	fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, (size_t) 1);
+
+	STAILQ_FOREACH(scn, &e->e_u.e_elf.e_scn, s_next) {
+		if (ec == ELFCLASS32)
+			src.d_buf = &scn->s_shdr.s_shdr32;
+		else
+			src.d_buf = &scn->s_shdr.s_shdr64;
+
+		dst.d_size = fsz;
+		dst.d_buf = nf + ex->ex_start + scn->s_ndx * fsz;
+
+		if (_libelf_xlate(&dst, &src, e->e_byteorder, ec,
+		    ELF_TOFILE) == NULL)
+			return ((off_t) -1);
+	}
+
+	return ((off_t) (ex->ex_start + nscn * fsz));
+}
+
+/*
+ * Write out the file image.
+ *
+ * The original file could have been mapped in with an ELF_C_RDWR
+ * command and the application could have added new content or
+ * re-arranged its sections before calling elf_update().  Consequently
+ * its not safe to work `in place' on the original file.  So we
+ * malloc() the required space for the updated ELF object and build
+ * the object there and write it out to the underlying file at the
+ * end.  Note that the application may have opened the underlying file
+ * in ELF_C_RDWR and only retrieved/modified a few sections.  We take
+ * care to avoid translating file sections unnecessarily.
+ *
+ * Gaps in the coverage of the file by the file's sections will be
+ * filled with the fill character set by elf_fill(3).
+ */
+
+static off_t
+_libelf_write_elf(Elf *e, off_t newsize, struct _Elf_Extent_List *extents)
+{
+	off_t nrc, rc;
+	Elf_Scn *scn, *tscn;
+	struct _Elf_Extent *ex;
+	unsigned char *newfile;
+
+	assert(e->e_kind == ELF_K_ELF);
+	assert(e->e_cmd == ELF_C_RDWR || e->e_cmd == ELF_C_WRITE);
+	assert(e->e_fd >= 0);
+
+	if ((newfile = malloc((size_t) newsize)) == NULL) {
+		LIBELF_SET_ERROR(RESOURCE, errno);
+		return ((off_t) -1);
+	}
+
+	nrc = rc = 0;
+	SLIST_FOREACH(ex, extents, ex_next) {
+
+		/* Fill inter-extent gaps. */
+		if (ex->ex_start > (size_t) rc)
+			(void) memset(newfile + rc, LIBELF_PRIVATE(fillchar),
+			    (size_t) (ex->ex_start - (uint64_t) rc));
+
+		switch (ex->ex_type) {
+		case ELF_EXTENT_EHDR:
+			if ((nrc = _libelf_write_ehdr(e, newfile, ex)) < 0)
+				goto error;
+			break;
+
+		case ELF_EXTENT_PHDR:
+			if ((nrc = _libelf_write_phdr(e, newfile, ex)) < 0)
+				goto error;
+			break;
+
+		case ELF_EXTENT_SECTION:
+			if ((nrc = _libelf_write_scn(e, newfile, ex)) < 0)
+				goto error;
+			break;
+
+		case ELF_EXTENT_SHDR:
+			if ((nrc = _libelf_write_shdr(e, newfile, ex)) < 0)
+				goto error;
+			break;
+
+		default:
+			assert(0);
+			break;
+		}
+
+		assert(ex->ex_start + ex->ex_size == (size_t) nrc);
+		assert(rc < nrc);
+
+		rc = nrc;
+	}
+
+	assert(rc == newsize);
+
+	/*
+	 * For regular files, throw away existing file content and
+	 * unmap any existing mappings.
+	 */
+	if ((e->e_flags & LIBELF_F_SPECIAL_FILE) == 0) {
+		if (ftruncate(e->e_fd, (off_t) 0) < 0 ||
+		    lseek(e->e_fd, (off_t) 0, SEEK_SET)) {
+			LIBELF_SET_ERROR(IO, errno);
+			goto error;
+		}
+#if	ELFTC_HAVE_MMAP
+		if (e->e_flags & LIBELF_F_RAWFILE_MMAP) {
+			assert(e->e_rawfile != NULL);
+			assert(e->e_cmd == ELF_C_RDWR);
+			if (munmap(e->e_rawfile, e->e_rawsize) < 0) {
+				LIBELF_SET_ERROR(IO, errno);
+				goto error;
+			}
+		}
+#endif
+	}
+
+	/*
+	 * Write out the new contents.
+	 */
+	if (write(e->e_fd, newfile, (size_t) newsize) != newsize) {
+		LIBELF_SET_ERROR(IO, errno);
+		goto error;
+	}
+
+	/*
+	 * For files opened in ELF_C_RDWR mode, set up the new 'raw'
+	 * contents.
+	 */
+	if (e->e_cmd == ELF_C_RDWR) {
+		assert(e->e_rawfile != NULL);
+		assert((e->e_flags & LIBELF_F_RAWFILE_MALLOC) ||
+		    (e->e_flags & LIBELF_F_RAWFILE_MMAP));
+		if (e->e_flags & LIBELF_F_RAWFILE_MALLOC) {
+			free(e->e_rawfile);
+			e->e_rawfile = newfile;
+			newfile = NULL;
+		}
+#if	ELFTC_HAVE_MMAP
+		else if (e->e_flags & LIBELF_F_RAWFILE_MMAP) {
+			if ((e->e_rawfile = mmap(NULL, (size_t) newsize,
+			    PROT_READ, MAP_PRIVATE, e->e_fd, (off_t) 0)) ==
+			    MAP_FAILED) {
+				LIBELF_SET_ERROR(IO, errno);
+				goto error;
+			}
+		}
+#endif	/* ELFTC_HAVE_MMAP */
+
+		/* Record the new size of the file. */
+		e->e_rawsize = (size_t) newsize;
+	} else {
+		/* File opened in ELF_C_WRITE mode. */
+		assert(e->e_rawfile == NULL);
+	}
+
+	/*
+	 * Reset flags, remove existing section descriptors and
+	 * {E,P}HDR pointers so that a subsequent elf_get{e,p}hdr()
+	 * and elf_getscn() will function correctly.
+	 */
+
+	e->e_flags &= ~ELF_F_DIRTY;
+
+	STAILQ_FOREACH_SAFE(scn, &e->e_u.e_elf.e_scn, s_next, tscn)
+		_libelf_release_scn(scn);
+
+	if (e->e_class == ELFCLASS32) {
+		free(e->e_u.e_elf.e_ehdr.e_ehdr32);
+		if (e->e_u.e_elf.e_phdr.e_phdr32)
+			free(e->e_u.e_elf.e_phdr.e_phdr32);
+
+		e->e_u.e_elf.e_ehdr.e_ehdr32 = NULL;
+		e->e_u.e_elf.e_phdr.e_phdr32 = NULL;
+	} else {
+		free(e->e_u.e_elf.e_ehdr.e_ehdr64);
+		if (e->e_u.e_elf.e_phdr.e_phdr64)
+			free(e->e_u.e_elf.e_phdr.e_phdr64);
+
+		e->e_u.e_elf.e_ehdr.e_ehdr64 = NULL;
+		e->e_u.e_elf.e_phdr.e_phdr64 = NULL;
+	}
+
+	/* Free the temporary buffer. */
+	if (newfile)
+		free(newfile);
+
+	return (rc);
+
+ error:
+	free(newfile);
+
+	return ((off_t) -1);
+}
+
+/*
+ * Update an ELF object.
+ */
+
+off_t
+elf_update(Elf *e, Elf_Cmd c)
+{
+	int ec;
+	off_t rc;
+	struct _Elf_Extent_List extents;
+
+	rc = (off_t) -1;
+
+	if (e == NULL || e->e_kind != ELF_K_ELF ||
+	    (c != ELF_C_NULL && c != ELF_C_WRITE)) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (rc);
+	}
+
+	if ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) {
+		LIBELF_SET_ERROR(CLASS, 0);
+		return (rc);
+	}
+
+	if (e->e_version == EV_NONE)
+		e->e_version = EV_CURRENT;
+
+	if (c == ELF_C_WRITE && e->e_cmd == ELF_C_READ) {
+		LIBELF_SET_ERROR(MODE, 0);
+		return (rc);
+	}
+
+	SLIST_INIT(&extents);
+
+	if ((rc = _libelf_resync_elf(e, &extents)) < 0)
+		goto done;
+
+	if (c == ELF_C_NULL)
+		goto done;
+
+	if (e->e_fd < 0) {
+		rc = (off_t) -1;
+		LIBELF_SET_ERROR(SEQUENCE, 0);
+		goto done;
+	}
+
+	rc = _libelf_write_elf(e, rc, &extents);
+
+done:
+	_libelf_release_extents(&extents);
+	e->e_flags &= ~LIBELF_F_SHDRS_LOADED;
+	return (rc);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_version.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,95 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elf_version.3 2123 2011-11-09 15:40:09Z jkoshy $
+.\"
+.Dd November 9, 2011
+.Os
+.Dt ELF_VERSION 3
+.Sh NAME
+.Nm elf_version
+.Nd retrieve or set ELF library operating version
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft unsigned int
+.Fn elf_version "unsigned int version"
+.Sh DESCRIPTION
+The
+.Fn elf_version
+function is used to query the current operating version of the ELF
+library, and to inform the ELF library about the application's desired
+operating version.
+.Pp
+If the argument
+.Ar version
+is
+.Dv EV_NONE ,
+the
+.Fn elf_version
+function returns the currently configured operating version for the
+ELF library.
+.Pp
+If the argument
+.Ar version
+is not
+.Dv EV_NONE ,
+and if argument
+.Ar version
+is supported by the ELF library, function
+.Fn elf_version
+sets the library's operating version to
+.Ar version ,
+and returns the previous value of the operating version.
+If argument
+.Ar version
+cannot be supported, then the
+.Fn elf_version
+function returns
+.Dv EV_NONE .
+.Sh RETURN VALUES
+The
+.Fn elf_version
+function returns the currently configured ELF library version, or
+.Dv EV_NONE
+if an unsupported version is requested.
+.Sh EXAMPLES
+An application program would inform the ELF library about its desired
+operating version and check for an error using the following code
+snippet:
+.Bd -literal -offset indent
+if (elf_version(EV_CURRENT) == EV_NONE)
+	err(EXIT_FAILURE, "ELF library too old");
+.Ed
+.Sh ERRORS
+Function
+.Fn elf_version
+may fail with the following error:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er "ELF_E_VERSION"
+An unsupported library version number was requested.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr gelf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/elf_version.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,50 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: elf_version.c 3174 2015-03-27 17:13:41Z emaste $");
+
+unsigned int
+elf_version(unsigned int v)
+{
+	unsigned int old;
+
+	if ((old = LIBELF_PRIVATE(version)) == EV_NONE)
+		old = EV_CURRENT;
+
+	if (v == EV_NONE)
+		return old;
+	if (v > EV_CURRENT) {
+		LIBELF_SET_ERROR(VERSION, 0);
+		return EV_NONE;
+	}
+
+	LIBELF_PRIVATE(version) = v;
+	return (old);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,200 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: gelf.3 3195 2015-05-12 17:22:19Z emaste $
+.\"
+.Dd September 1, 2006
+.Os
+.Dt GELF 3
+.Sh NAME
+.Nm GElf
+.Nd class-independent API for ELF manipulation
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In gelf.h
+.Sh DESCRIPTION
+This manual page describes a class independent API for manipulating
+ELF objects.
+This API allows an application to operate on ELF descriptors without
+needing to the know the ELF class of the descriptor.
+.Pp
+The GElf API may be used alongside the ELF API without restriction.
+.Ss GElf Data Structures
+The GElf API defines the following class-independent data structures:
+.Bl -tag -width GElf_Sxword
+.It Vt GElf_Addr
+A representation of ELF addresses.
+.It Vt GElf_Dyn
+A class-independent representation of ELF
+.Sy .dynamic
+section entries.
+.It Vt GElf_Ehdr
+A class-independent representation of an ELF Executable Header.
+.It Vt GElf_Half
+An unsigned 16 bit quantity.
+.It Vt GElf_Off
+A class-independent representation of a ELF offset.
+.It Vt GElf_Phdr
+A class-independent representation of an ELF Program Header Table
+entry.
+.It Vt GElf_Rel
+A class-independent representation of an ELF relocation entry.
+.It Vt GElf_Rela
+A class-independent representation of an ELF relocation entry with
+addend.
+.It Vt GElf_Shdr
+A class-independent representation of an ELF Section Header Table
+entry.
+.It Vt GElf_Sword
+A signed 32 bit quantity.
+.It Vt GElf_Sxword
+A signed 64 bit quantity.
+.It Vt GElf_Sym
+A class-independent representation of an ELF symbol table entry.
+.It Vt GElf_Word
+An unsigned 32 bit quantity.
+.It Vt GElf_Xword
+An unsigned 64 bit quantity.
+.El
+.Pp
+These data structures are sized to be compatible with the
+corresponding 64 bit ELF structures, and have the same internal
+structure as their 64 bit class-dependent counterparts.
+Class-dependent ELF structures are described in
+.Xr elf 5 .
+.Ss GElf Programming Model
+GElf functions always return a
+.Em copy
+of the underlying (class-dependent) ELF data structure.
+The programming model with GElf is as follows:
+.Bl -enum
+.It
+An application will retrieve data from an ELF descriptor using a
+.Fn gelf_get_*
+function.
+This will copy out data into a private
+.Vt GElf_*
+data structure.
+.It
+The application will work with its private copy of the GElf
+structure.
+.It
+Once done, the application copies the new values back to the
+underlying ELF data structure using the
+.Fn gelf_update_*
+functions.
+.It
+The application will then use the
+.Fn elf_flag*
+APIs to indicate to the ELF library that an ELF data structure is dirty.
+.El
+.Pp
+When updating an underlying 32 bit ELF data structure, the GElf
+routines will signal an error if a GElf value is out of range
+for the underlying ELF data type.
+.Ss Namespace use
+The GElf interface uses the following symbols:
+.Bl -tag
+.It GElf_*
+Class-independent data types.
+.It gelf_*
+For functions defined in the API set.
+.El
+.Ss GElf Programming APIs
+This section provides an overview of the GElf programming APIs.
+Further information is provided in the manual page of each function
+listed here.
+.Bl -tag
+.It "Allocating ELF Data Structures"
+.Bl -tag -compact
+.It Fn gelf_newehdr
+Allocate a new ELF Executable Header.
+.It Fn gelf_newphdr
+Allocate a new ELF Program Header Table.
+.El
+.It "Data Translation"
+.Bl -tag -compact
+.It Fn gelf_xlatetof
+Translate the native representation of an ELF data structure to its
+file representation.
+.It Fn gelf_xlatetom
+Translate from the file representation of an ELF data structure to a
+native representation.
+.El
+.It "Retrieving ELF Data"
+.Bl -tag -compact
+.It Fn gelf_getdyn
+Retrieve an ELF
+.Sy .dynamic
+table entry.
+.It Fn gelf_getehdr
+Retrieve an ELF Executable Header from the underlying ELF descriptor.
+.It Fn gelf_getphdr
+Retrieve an ELF Program Header Table entry from the underlying ELF descriptor.
+.It Fn gelf_getrel
+Retrieve an ELF relocation entry.
+.It Fn gelf_getrela
+Retrieve an ELF relocation entry with addend.
+.It Fn gelf_getshdr
+Retrieve an ELF Section Header Table entry from the underlying ELF descriptor.
+.It Fn gelf_getsym
+Retrieve an ELF symbol table entry.
+.El
+.It Queries
+.Bl -tag -compact
+.It Fn gelf_checksum
+Retrieves the ELF checksum for an ELF descriptor.
+.It Fn gelf_fsize
+Retrieves the size of the file representation of an ELF type.
+.It Fn gelf_getclass
+Retrieves the ELF class of an ELF descriptor.
+.El
+.It "Updating ELF Data"
+.Bl -tag -compact -width ".Fn gelf_update_shdr"
+.It Fn gelf_update_dyn
+Copy back an ELF
+.Sy .dynamic
+Table entry.
+.It Fn gelf_update_phdr
+Copy back an ELF Program Header Table entry.
+.It Fn gelf_update_rel
+Copy back an ELF relocation entry.
+.It Fn gelf_update_rela
+Copy back an ELF relocation with addend entry.
+.It Fn gelf_update_shdr
+Copy back an ELF Section Header Table entry.
+.It Fn gelf_update_sym
+Copy back an ELF symbol table entry.
+.El
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf 5
+.Sh HISTORY
+The GELF(3) API first appeared in System V Release 4.
+This implementation of the API first appeared in
+.Fx 7.0 .
+.Sh AUTHORS
+The GElf API was implemented by
+.An Joseph Koshy Aq Mt jkoshy@FreeBSD.org .
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf.h	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,110 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: gelf.h 3174 2015-03-27 17:13:41Z emaste $
+ */
+
+#ifndef	_GELF_H_
+#define	_GELF_H_
+
+#include <libelf.h>
+
+typedef Elf64_Addr	GElf_Addr;	/* Addresses */
+typedef Elf64_Half	GElf_Half;	/* Half words (16 bit) */
+typedef Elf64_Off	GElf_Off;	/* Offsets */
+typedef Elf64_Sword	GElf_Sword;	/* Signed words (32 bit) */
+typedef Elf64_Sxword	GElf_Sxword;	/* Signed long words (64 bit) */
+typedef Elf64_Word	GElf_Word;	/* Unsigned words (32 bit) */
+typedef Elf64_Xword	GElf_Xword;	/* Unsigned long words (64 bit) */
+
+typedef Elf64_Dyn	GElf_Dyn;	/* ".dynamic" section entries */
+typedef Elf64_Ehdr	GElf_Ehdr;	/* ELF header */
+typedef Elf64_Phdr	GElf_Phdr;	/* Program header */
+typedef Elf64_Shdr	GElf_Shdr;	/* Section header */
+typedef Elf64_Sym	GElf_Sym;	/* Symbol table entries */
+typedef Elf64_Rel	GElf_Rel;	/* Relocation entries */
+typedef Elf64_Rela	GElf_Rela;	/* Relocation entries with addend */
+
+typedef	Elf64_Cap	GElf_Cap;	/* SW/HW capabilities */
+typedef Elf64_Move	GElf_Move;	/* Move entries */
+typedef Elf64_Syminfo	GElf_Syminfo;	/* Symbol information */
+
+#define	GELF_M_INFO			ELF64_M_INFO
+#define	GELF_M_SIZE			ELF64_M_SIZE
+#define	GELF_M_SYM			ELF64_M_SYM
+
+#define	GELF_R_INFO			ELF64_R_INFO
+#define	GELF_R_SYM			ELF64_R_SYM
+#define	GELF_R_TYPE			ELF64_R_TYPE
+#define	GELF_R_TYPE_DATA		ELF64_R_TYPE_DATA
+#define	GELF_R_TYPE_ID			ELF64_R_TYPE_ID
+#define	GELF_R_TYPE_INFO		ELF64_R_TYPE_INFO
+
+#define	GELF_ST_BIND			ELF64_ST_BIND
+#define	GELF_ST_INFO			ELF64_ST_INFO
+#define	GELF_ST_TYPE			ELF64_ST_TYPE
+#define	GELF_ST_VISIBILITY		ELF64_ST_VISIBILITY
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+long		gelf_checksum(Elf *_elf);
+size_t		gelf_fsize(Elf *_elf, Elf_Type _type, size_t _count,
+			unsigned int _version);
+int		gelf_getclass(Elf *_elf);
+GElf_Dyn	*gelf_getdyn(Elf_Data *_data, int _index, GElf_Dyn *_dst);
+GElf_Ehdr	*gelf_getehdr(Elf *_elf, GElf_Ehdr *_dst);
+GElf_Phdr	*gelf_getphdr(Elf *_elf, int _index, GElf_Phdr *_dst);
+GElf_Rel	*gelf_getrel(Elf_Data *_src, int _index, GElf_Rel *_dst);
+GElf_Rela	*gelf_getrela(Elf_Data *_src, int _index, GElf_Rela *_dst);
+GElf_Shdr	*gelf_getshdr(Elf_Scn *_scn, GElf_Shdr *_dst);
+GElf_Sym	*gelf_getsym(Elf_Data *_src, int _index, GElf_Sym *_dst);
+GElf_Sym	*gelf_getsymshndx(Elf_Data *_src, Elf_Data *_shindexsrc,
+			int _index, GElf_Sym *_dst, Elf32_Word *_shindexdst);
+void *		gelf_newehdr(Elf *_elf, int _class);
+void *		gelf_newphdr(Elf *_elf, size_t _phnum);
+int		gelf_update_dyn(Elf_Data *_dst, int _index, GElf_Dyn *_src);
+int		gelf_update_ehdr(Elf *_elf, GElf_Ehdr *_src);
+int		gelf_update_phdr(Elf *_elf, int _index, GElf_Phdr *_src);
+int		gelf_update_rel(Elf_Data *_dst, int _index, GElf_Rel *_src);
+int		gelf_update_rela(Elf_Data *_dst, int _index, GElf_Rela *_src);
+int		gelf_update_shdr(Elf_Scn *_dst, GElf_Shdr *_src);
+int		gelf_update_sym(Elf_Data *_dst, int _index, GElf_Sym *_src);
+int		gelf_update_symshndx(Elf_Data *_symdst, Elf_Data *_shindexdst,
+			int _index, GElf_Sym *_symsrc, Elf32_Word _shindexsrc);
+Elf_Data 	*gelf_xlatetof(Elf *_elf, Elf_Data *_dst, const Elf_Data *_src, unsigned int _encode);
+Elf_Data 	*gelf_xlatetom(Elf *_elf, Elf_Data *_dst, const Elf_Data *_src, unsigned int _encode);
+
+GElf_Cap	*gelf_getcap(Elf_Data *_data, int _index, GElf_Cap *_cap);
+GElf_Move	*gelf_getmove(Elf_Data *_src, int _index, GElf_Move *_dst);
+GElf_Syminfo	*gelf_getsyminfo(Elf_Data *_src, int _index, GElf_Syminfo *_dst);
+int		gelf_update_cap(Elf_Data *_dst, int _index, GElf_Cap *_src);
+int		gelf_update_move(Elf_Data *_dst, int _index, GElf_Move *_src);
+int		gelf_update_syminfo(Elf_Data *_dst, int _index, GElf_Syminfo *_src);
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _GELF_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_cap.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,150 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <gelf.h>
+#include <limits.h>
+#include <stdint.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: gelf_cap.c 3177 2015-03-30 18:19:41Z emaste $");
+
+GElf_Cap *
+gelf_getcap(Elf_Data *ed, int ndx, GElf_Cap *dst)
+{
+	int ec;
+	Elf *e;
+	size_t msz;
+	Elf_Scn *scn;
+	Elf32_Cap *cap32;
+	Elf64_Cap *cap64;
+	uint32_t sh_type;
+	struct _Libelf_Data *d;
+
+	d = (struct _Libelf_Data *) ed;
+
+	if (d == NULL || ndx < 0 || dst == NULL ||
+	    (scn = d->d_scn) == NULL ||
+	    (e = scn->s_elf) == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	ec = e->e_class;
+	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
+
+	if (ec == ELFCLASS32)
+		sh_type = scn->s_shdr.s_shdr32.sh_type;
+	else
+		sh_type = scn->s_shdr.s_shdr64.sh_type;
+
+	if (_libelf_xlate_shtype(sh_type) != ELF_T_CAP) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	msz = _libelf_msize(ELF_T_CAP, ec, e->e_version);
+
+	assert(msz > 0);
+
+	if (msz * (size_t) ndx >= d->d_data.d_size) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	if (ec == ELFCLASS32) {
+
+		cap32 = (Elf32_Cap *) d->d_data.d_buf + ndx;
+
+		dst->c_tag  = cap32->c_tag;
+		dst->c_un.c_val = (Elf64_Xword) cap32->c_un.c_val;
+
+	} else {
+
+		cap64 = (Elf64_Cap *) d->d_data.d_buf + ndx;
+
+		*dst = *cap64;
+	}
+
+	return (dst);
+}
+
+int
+gelf_update_cap(Elf_Data *ed, int ndx, GElf_Cap *gc)
+{
+	int ec;
+	Elf *e;
+	size_t msz;
+	Elf_Scn *scn;
+	Elf32_Cap *cap32;
+	Elf64_Cap *cap64;
+	uint32_t sh_type;
+	struct _Libelf_Data *d;
+
+	d = (struct _Libelf_Data *) ed;
+
+	if (d == NULL || ndx < 0 || gc == NULL ||
+	    (scn = d->d_scn) == NULL ||
+	    (e = scn->s_elf) == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	ec = e->e_class;
+	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
+
+	if (ec == ELFCLASS32)
+		sh_type = scn->s_shdr.s_shdr32.sh_type;
+	else
+		sh_type = scn->s_shdr.s_shdr64.sh_type;
+
+	if (_libelf_xlate_shtype(sh_type) != ELF_T_CAP) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	msz = _libelf_msize(ELF_T_CAP, ec, e->e_version);
+	assert(msz > 0);
+
+	if (msz * (size_t) ndx >= d->d_data.d_size) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	if (ec == ELFCLASS32) {
+		cap32 = (Elf32_Cap *) d->d_data.d_buf + ndx;
+
+		LIBELF_COPY_U32(cap32, gc, c_tag);
+		LIBELF_COPY_U32(cap32, gc, c_un.c_val);
+	} else {
+		cap64 = (Elf64_Cap *) d->d_data.d_buf + ndx;
+
+		*cap64 = *gc;
+	}
+
+	return (1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_checksum.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,115 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: gelf_checksum.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd August 29, 2006
+.Os
+.Dt GELF_CHECKSUM 3
+.Sh NAME
+.Nm elf32_checksum ,
+.Nm elf64_checksum ,
+.Nm gelf_checksum
+.Nd return the checksum of an ELF object
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft long
+.Fn elf32_checksum "Elf *elf"
+.Ft long
+.Fn elf64_checksum "Elf *elf"
+.In gelf.h
+.Ft long
+.Fn gelf_checksum "Elf *elf"
+.Sh DESCRIPTION
+These functions return a simple checksum of the ELF object described
+by their argument
+.Ar elf .
+The checksum is computed in way that allows its value to remain
+unchanged in presence of modifications to the ELF object by utilities
+like
+.Xr strip 1 .
+.Pp
+Function
+.Fn elf32_checksum
+returns a checksum for an ELF descriptor
+.Ar elf
+of class
+.Dv ELFCLASS32 .
+.Pp
+Function
+.Fn elf64_checksum
+returns a checksum for an ELF descriptor
+.Ar elf
+of class
+.Dv ELFCLASS64 .
+.Pp
+Function
+.Fn gelf_checksum
+provides a class-independent way retrieving the checksum
+for ELF object
+.Ar elf .
+.Sh RETURN VALUES
+These functions return the checksum of the ELF object, or zero in case
+an error was encountered.
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was NULL.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was not a descriptor for an ELF file.
+.It Bq Er ELF_E_ARGUMENT
+The ELF descriptor
+.Ar elf
+was not opened for reading or updating.
+.It Bq Er ELF_E_CLASS
+For functions
+.Fn elf32_checksum
+and
+.Fn elf64_checksum ,
+ELF descriptor
+.Ar elf
+did not match the class of the called function.
+.It Bq Er ELF_E_HEADER
+The ELF object specified by argument
+.Ar elf
+had a malformed executable header.
+.It Bq Er ELF_E_RESOURCE
+An out of memory condition was detected during processing.
+.It Bq Er ELF_E_SECTION
+The ELF object specified by argument
+.Ar elf
+contained a section with a malformed section header.
+.It Bq Er ELF_E_VERSION
+The ELF object was of an unsupported version.
+.El
+.Sh SEE ALSO
+.Xr strip 1 ,
+.Xr elf 3 ,
+.Xr gelf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_checksum.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <gelf.h>
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: gelf_checksum.c 3174 2015-03-27 17:13:41Z emaste $");
+
+long
+elf32_checksum(Elf *e)
+{
+	return (_libelf_checksum(e, ELFCLASS32));
+}
+
+long
+elf64_checksum(Elf *e)
+{
+	return (_libelf_checksum(e, ELFCLASS64));
+}
+
+long
+gelf_checksum(Elf *e)
+{
+	int ec;
+	if (e == NULL ||
+	    ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0L);
+	}
+	return (_libelf_checksum(e, ec));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_dyn.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,152 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <gelf.h>
+#include <limits.h>
+#include <stdint.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: gelf_dyn.c 3177 2015-03-30 18:19:41Z emaste $");
+
+GElf_Dyn *
+gelf_getdyn(Elf_Data *ed, int ndx, GElf_Dyn *dst)
+{
+	int ec;
+	Elf *e;
+	size_t msz;
+	Elf_Scn *scn;
+	Elf32_Dyn *dyn32;
+	Elf64_Dyn *dyn64;
+	uint32_t sh_type;
+	struct _Libelf_Data *d;
+
+	d = (struct _Libelf_Data *) ed;
+
+	if (d == NULL || ndx < 0 || dst == NULL ||
+	    (scn = d->d_scn) == NULL ||
+	    (e = scn->s_elf) == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	ec = e->e_class;
+	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
+
+	if (ec == ELFCLASS32)
+		sh_type = scn->s_shdr.s_shdr32.sh_type;
+	else
+		sh_type = scn->s_shdr.s_shdr64.sh_type;
+
+	if (_libelf_xlate_shtype(sh_type) != ELF_T_DYN) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	msz = _libelf_msize(ELF_T_DYN, ec, e->e_version);
+
+	assert(msz > 0);
+	assert(ndx >= 0);
+
+	if (msz * (size_t) ndx >= d->d_data.d_size) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	if (ec == ELFCLASS32) {
+		dyn32 = (Elf32_Dyn *) d->d_data.d_buf + ndx;
+
+		dst->d_tag      = dyn32->d_tag;
+		dst->d_un.d_val = (Elf64_Xword) dyn32->d_un.d_val;
+
+	} else {
+
+		dyn64 = (Elf64_Dyn *) d->d_data.d_buf + ndx;
+
+		*dst = *dyn64;
+	}
+
+	return (dst);
+}
+
+int
+gelf_update_dyn(Elf_Data *ed, int ndx, GElf_Dyn *ds)
+{
+	int ec;
+	Elf *e;
+	size_t msz;
+	Elf_Scn *scn;
+	Elf32_Dyn *dyn32;
+	Elf64_Dyn *dyn64;
+	uint32_t sh_type;
+	struct _Libelf_Data *d;
+
+	d = (struct _Libelf_Data *) ed;
+
+	if (d == NULL || ndx < 0 || ds == NULL ||
+	    (scn = d->d_scn) == NULL ||
+	    (e = scn->s_elf) == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	ec = e->e_class;
+	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
+
+	if (ec == ELFCLASS32)
+		sh_type = scn->s_shdr.s_shdr32.sh_type;
+	else
+		sh_type = scn->s_shdr.s_shdr64.sh_type;
+
+	if (_libelf_xlate_shtype(sh_type) != ELF_T_DYN) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	msz = _libelf_msize(ELF_T_DYN, ec, e->e_version);
+
+	assert(msz > 0);
+	assert(ndx >= 0);
+
+	if (msz * (size_t) ndx >= d->d_data.d_size) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	if (ec == ELFCLASS32) {
+		dyn32 = (Elf32_Dyn *) d->d_data.d_buf + ndx;
+
+		LIBELF_COPY_S32(dyn32, ds, d_tag);
+		LIBELF_COPY_U32(dyn32, ds, d_un.d_val);
+	} else {
+		dyn64 = (Elf64_Dyn *) d->d_data.d_buf + ndx;
+
+		*dyn64 = *ds;
+	}
+
+	return (1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_ehdr.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,167 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <gelf.h>
+#include <libelf.h>
+#include <limits.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: gelf_ehdr.c 3177 2015-03-30 18:19:41Z emaste $");
+
+Elf32_Ehdr *
+elf32_getehdr(Elf *e)
+{
+	return (_libelf_ehdr(e, ELFCLASS32, 0));
+}
+
+Elf64_Ehdr *
+elf64_getehdr(Elf *e)
+{
+	return (_libelf_ehdr(e, ELFCLASS64, 0));
+}
+
+GElf_Ehdr *
+gelf_getehdr(Elf *e, GElf_Ehdr *d)
+{
+	int ec;
+	Elf32_Ehdr *eh32;
+	Elf64_Ehdr *eh64;
+
+	if (d == NULL || e == NULL ||
+	    ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	if (ec == ELFCLASS32) {
+		if ((eh32 = _libelf_ehdr(e, ELFCLASS32, 0)) == NULL)
+			return (NULL);
+
+		(void) memcpy(d->e_ident, eh32->e_ident,
+		    sizeof(eh32->e_ident));
+		d->e_type		= eh32->e_type;
+		d->e_machine		= eh32->e_machine;
+		d->e_version		= eh32->e_version;
+		d->e_entry		= eh32->e_entry;
+		d->e_phoff		= eh32->e_phoff;
+		d->e_shoff		= eh32->e_shoff;
+		d->e_flags		= eh32->e_flags;
+		d->e_ehsize		= eh32->e_ehsize;
+		d->e_phentsize		= eh32->e_phentsize;
+		d->e_phnum		= eh32->e_phnum;
+		d->e_shentsize		= eh32->e_shentsize;
+		d->e_shnum		= eh32->e_shnum;
+		d->e_shstrndx		= eh32->e_shstrndx;
+
+		return (d);
+	}
+
+	assert(ec == ELFCLASS64);
+
+	if ((eh64 = _libelf_ehdr(e, ELFCLASS64, 0)) == NULL)
+		return (NULL);
+	*d = *eh64;
+
+	return (d);
+}
+
+Elf32_Ehdr *
+elf32_newehdr(Elf *e)
+{
+	return (_libelf_ehdr(e, ELFCLASS32, 1));
+}
+
+Elf64_Ehdr *
+elf64_newehdr(Elf *e)
+{
+	return (_libelf_ehdr(e, ELFCLASS64, 1));
+}
+
+void *
+gelf_newehdr(Elf *e, int ec)
+{
+	if (e != NULL &&
+	    (ec == ELFCLASS32 || ec == ELFCLASS64))
+		return (_libelf_ehdr(e, ec, 1));
+
+	LIBELF_SET_ERROR(ARGUMENT, 0);
+	return (NULL);
+}
+
+int
+gelf_update_ehdr(Elf *e, GElf_Ehdr *s)
+{
+	int ec;
+	void *ehdr;
+	Elf32_Ehdr *eh32;
+	Elf64_Ehdr *eh64;
+
+	if (s== NULL || e == NULL || e->e_kind != ELF_K_ELF ||
+	    ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	if (e->e_cmd == ELF_C_READ) {
+		LIBELF_SET_ERROR(MODE, 0);
+		return (0);
+	}
+
+	if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL)
+		return (0);
+
+	(void) elf_flagehdr(e, ELF_C_SET, ELF_F_DIRTY);
+
+	if (ec == ELFCLASS64) {
+		eh64 = (Elf64_Ehdr *) ehdr;
+		*eh64 = *s;
+		return (1);
+	}
+
+	eh32 = (Elf32_Ehdr *) ehdr;
+
+	(void) memcpy(eh32->e_ident, s->e_ident, sizeof(eh32->e_ident));
+
+	eh32->e_type      = s->e_type;
+	eh32->e_machine   = s->e_machine;
+	eh32->e_version   = s->e_version;
+	LIBELF_COPY_U32(eh32, s, e_entry);
+	LIBELF_COPY_U32(eh32, s, e_phoff);
+	LIBELF_COPY_U32(eh32, s, e_shoff);
+	eh32->e_flags     = s->e_flags;
+	eh32->e_ehsize    = s->e_ehsize;
+	eh32->e_phentsize = s->e_phentsize;
+	eh32->e_phnum     = s->e_phnum;
+	eh32->e_shentsize = s->e_shentsize;
+	eh32->e_shnum     = s->e_shnum;
+	eh32->e_shstrndx  = s->e_shstrndx;
+
+	return (1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_fsize.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,96 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: gelf_fsize.3 317 2009-03-06 17:29:22Z jkoshy $
+.\"
+.Dd February 5, 2008
+.Os
+.Dt GELF_FSIZE 3
+.Sh NAME
+.Nm gelf_fsize ,
+.Nm elf32_fsize ,
+.Nm elf64_fsize
+.Nd return the size of a file type
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft size_t
+.Fn elf32_fsize "Elf_Type type" "size_t count" "unsigned int version"
+.Ft size_t
+.Fn elf64_fsize "Elf_Type type" "size_t count" "unsigned int version"
+.In gelf.h
+.Ft size_t
+.Fn gelf_fsize "Elf *elf" "Elf_Type type" "size_t count" "unsigned int version"
+.Sh DESCRIPTION
+These functions return the size in bytes of the file representation of
+.Ar count
+numbers of objects of ELF type
+.Ar type .
+For ELF types that are of variable length, these functions return a
+size of one byte.
+.Pp
+Functions
+.Fn elf32_fsize
+and
+.Fn elf64_fsize
+return sizes for files of class
+.Dv ELFCLASS32
+and
+.Dv ELFCLASS64
+respectively.
+Function
+.Fn gelf_fsize
+returns the size for the class of ELF descriptor
+.Ar elf .
+.Sh RETURN VALUES
+These functions return a non-zero value in case of success, or zero in
+case of an error.
+.Sh ERRORS
+These functions may fail with:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was NULL in a call to
+.Fn gelf_fsize .
+.It Bq Er ELF_E_ARGUMENT
+ELF descriptor
+.Ar elf
+had an unknown ELF class.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar type
+contained an illegal value.
+.It Bq Er ELF_E_UNIMPL
+Support for ELF type
+.Ar type
+has not been implemented.
+.It Bq Er ELF_E_VERSION
+Argument
+.Ar version
+is not a supported version.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr gelf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_fsize.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <gelf.h>
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: gelf_fsize.c 3174 2015-03-27 17:13:41Z emaste $");
+
+size_t
+elf32_fsize(Elf_Type t, size_t c, unsigned int v)
+{
+	return (_libelf_fsize(t, ELFCLASS32, v, c));
+}
+
+size_t
+elf64_fsize(Elf_Type t, size_t c, unsigned int v)
+{
+	return (_libelf_fsize(t, ELFCLASS64, v, c));
+}
+
+size_t
+gelf_fsize(Elf *e, Elf_Type t, size_t c, unsigned int v)
+{
+
+	if (e == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	if (e->e_class == ELFCLASS32 || e->e_class == ELFCLASS64)
+		return (_libelf_fsize(t, e->e_class, v, c));
+
+	LIBELF_SET_ERROR(ARGUMENT, 0);
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_getcap.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,121 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: gelf_getcap.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd August 29, 2006
+.Os
+.Dt GELF_GETCAP 3
+.Sh NAME
+.Nm gelf_getcap ,
+.Nm gelf_update_cap
+.Nd read and update ELF capability information
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In gelf.h
+.Ft "GElf_Cap *"
+.Fn gelf_getcap "Elf_Data *data" "int ndx" "GElf_Cap *cap"
+.Ft int
+.Fn gelf_update_cap "Elf_Data *data" "int ndx" "GElf_Cap *cap"
+.Sh DESCRIPTION
+These convenience functions are used to retrieve and update class-dependent
+.Vt Elf32_Cap
+or
+.Vt Elf64_Cap
+information.
+.Pp
+Argument
+.Ar data
+is an
+.Vt Elf_Data
+descriptor associated with a section of type
+.Dv SHT_SUNW_cap .
+Argument
+.Ar ndx
+is the index of the entry being retrieved or updated.
+The class-independent
+.Vt GElf_Cap
+structure is described in
+.Xr gelf 3 .
+.Pp
+Function
+.Fn gelf_getcap
+retrieves the class-dependent entry at index
+.Ar ndx
+in data buffer
+.Ar data
+and copies it to the destination pointed to by argument
+.Ar cap
+after translation to class-independent form.
+.Pp
+Function
+.Fn gelf_update_cap
+converts the class-independent entry pointed to
+by argument
+.Ar cap
+to class-dependent form, and writes it to the entry at index
+.Ar ndx
+in the data buffer described by argument
+.Ar data .
+Function
+.Fn gelf_update_cap
+signals an error if any of the values in the class-independent
+representation exceeds the representable limits of the target
+type.
+.Sh RETURN VALUES
+Function
+.Fn gelf_getcap
+returns the value of argument
+.Ar cap
+if successful, or NULL in case of an error.
+Function
+.Fn gelf_update_cap
+returns a non-zero value if successful, or zero in case of an error.
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+Arguments
+.Ar data
+or
+.Ar cap
+were NULL.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar ndx
+was less than zero or larger than the number of entries in the data
+descriptor.
+.It Bq Er ELF_E_ARGUMENT
+Data descriptor
+.Ar data
+was not associated with a section of type
+.Dv SHT_SUNW_cap .
+.It Bq Er ELF_E_RANGE
+A value was not representable in the target type.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_getdata 3 ,
+.Xr elf_getscn 3 ,
+.Xr gelf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_getclass.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,61 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: gelf_getclass.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd July 3, 2006
+.Os
+.Dt GELF_GETCLASS 3
+.Sh NAME
+.Nm gelf_getclass
+.Nd retrieve the class of an ELF descriptor
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In gelf.h
+.Ft int
+.Fn gelf_getclass "Elf *elf"
+.Sh DESCRIPTION
+Function
+.Fn gelf_getclass
+returns the ELF class of the descriptor supplied in argument
+.Ar elf .
+.Sh RETURN VALUES
+Function
+.Fn gelf_getclass
+will return one of
+.Dv ELFCLASS32
+or
+.Dv ELFCLASS64
+if the argument
+.Ar elf
+is a descriptor for an ELF file.
+The value
+.Dv ELFCLASSNONE
+is returned if argument
+.Ar elf
+was null, or if it was not a descriptor for an ELF file.
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_kind 3 ,
+.Xr gelf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_getclass.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <gelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: gelf_getclass.c 3174 2015-03-27 17:13:41Z emaste $");
+
+int
+gelf_getclass(Elf *e)
+{
+	return (e != NULL ? e->e_class : ELFCLASSNONE);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_getdyn.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,123 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: gelf_getdyn.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd August 29, 2006
+.Os
+.Dt GELF_GETDYN 3
+.Sh NAME
+.Nm gelf_getdyn ,
+.Nm gelf_update_dyn
+.Nd read and update ELF dynamic entries
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In gelf.h
+.Ft "GElf_Dyn *"
+.Fn gelf_getdyn "Elf_Data *data" "int ndx" "GElf_Dyn *dyn"
+.Ft int
+.Fn gelf_update_dyn "Elf_Data *data" "int ndx" "GElf_Dyn *dyn"
+.Sh DESCRIPTION
+These convenience functions are used to retrieve and update class-dependent
+.Vt Elf32_Dyn
+or
+.Vt Elf64_Dyn
+information in the
+.Sy dynamic
+table of an ELF object.
+.Pp
+Argument
+.Ar data
+is an
+.Vt Elf_Data
+descriptor associated with a section of type
+.Dv SHT_DYNAMIC .
+Argument
+.Ar ndx
+is the index of the entry being retrieved or updated.
+The class-independent
+.Vt GElf_Dyn
+structure is described in
+.Xr gelf 3 .
+.Pp
+Function
+.Fn gelf_getdyn
+retrieves the class-dependent entry at index
+.Ar ndx
+in data buffer
+.Ar data
+and copies it to the destination pointed to by argument
+.Ar dyn
+after translation to class-independent form.
+.Pp
+Function
+.Fn gelf_update_dyn
+converts the class-independent entry pointed to
+by argument
+.Ar dyn
+to class-dependent form, and writes it to the entry at index
+.Ar ndx
+in the data buffer described by argument
+.Ar data .
+Function
+.Fn gelf_update_dyn
+signals an error if any of the values in the class-independent
+representation exceeds the representable limits of the target
+type.
+.Sh RETURN VALUES
+Function
+.Fn gelf_getdyn
+returns the value of argument
+.Ar dyn
+if successful, or NULL in case of an error.
+Function
+.Fn gelf_update_dyn
+returns a non-zero value if successful, or zero in case of an error.
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+Arguments
+.Ar data
+or
+.Ar dyn
+were NULL.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar ndx
+was less than zero or larger than the number of entries in the data
+descriptor.
+.It Bq Er ELF_E_ARGUMENT
+Data descriptor
+.Ar data
+was not associated with a section of type
+.Dv SHT_DYNAMIC .
+.It Bq Er ELF_E_RANGE
+A value was not representable in the target type.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_getdata 3 ,
+.Xr elf_getscn 3 ,
+.Xr gelf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_getehdr.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,123 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: gelf_getehdr.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd December 16, 2006
+.Os
+.Dt GELF_GETEHDR 3
+.Sh NAME
+.Nm elf32_getehdr ,
+.Nm elf64_getehdr ,
+.Nm gelf_getehdr
+.Nd retrieve the object file header
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft "Elf32_Ehdr *"
+.Fn elf32_getehdr "Elf *elf"
+.Ft "Elf64_Ehdr *"
+.Fn elf64_getehdr "Elf *elf"
+.In gelf.h
+.Ft "GElf_Ehdr *"
+.Fn gelf_getehdr "Elf *elf" "GElf_Ehdr *dst"
+.Sh DESCRIPTION
+These functions retrieve the ELF object file
+header from the ELF descriptor
+.Ar elf
+and return a translated header descriptor to their callers.
+.Pp
+Functions
+.Fn elf32_getehdr
+and
+.Fn elf64_getehdr
+return a pointer to the appropriate class-specific header descriptor
+if it exists in the file referenced by descriptor
+.Ar elf .
+These functions return
+.Dv NULL
+if an ELF header was not found in file
+.Ar elf .
+.Pp
+Function
+.Fn gelf_getehdr
+stores a translated copy of the header for ELF file
+.Ar elf
+into the descriptor pointed to by argument
+.Ar dst .
+It returns argument
+.Ar dst
+if successful or
+.Dv NULL
+in case of failure.
+.Sh RETURN VALUES
+These functions return a pointer to a translated header descriptor
+if successful, or NULL on failure.
+.Sh ERRORS
+These functions can fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+The argument
+.Ar elf
+was null.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was not a descriptor for an ELF file.
+.It Bq Er ELF_E_ARGUMENT
+The elf class of descriptor
+.Ar elf
+was not recognized.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar dst
+was null.
+.It Bq Er ELF_E_CLASS
+The ELF class of descriptor
+.Ar elf
+did not match that of the API function being called.
+.It Bq Er ELF_E_HEADER
+ELF descriptor
+.Ar elf
+does not have an associated header.
+.It Bq Er ELF_E_RESOURCE
+An out of memory condition was detected during execution.
+.It Bq Er ELF_E_SECTION
+The ELF descriptor in argument
+.Ar elf
+did not adhere to the conventions used for extended numbering.
+.It Bq Er ELF_E_VERSION
+The ELF descriptor
+.Ar elf
+had an unsupported ELF version number.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf32_newehdr 3 ,
+.Xr elf64_newehdr 3 ,
+.Xr elf_flagehdr 3 ,
+.Xr elf_getident 3 ,
+.Xr gelf 3 ,
+.Xr gelf_newehdr 3 ,
+.Xr elf 5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_getmove.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,120 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: gelf_getmove.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd August 29, 2006
+.Os
+.Dt GELF_GETMOVE 3
+.Sh NAME
+.Nm gelf_getmove ,
+.Nm gelf_update_move
+.Nd read and update Elf Move information
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In gelf.h
+.Ft "GElf_Move *"
+.Fn gelf_getmove "Elf_Data *data" "int ndx" "GElf_Move *move"
+.Ft int
+.Fn gelf_update_move "Elf_Data *data" "int ndx" "GElf_Move *move"
+.Sh DESCRIPTION
+These convenience functions are used to retrieve and update class-dependent
+.Vt Elf32_Move
+and
+.Vt Elf64_Move
+structures in an ELF object.
+.Pp
+Argument
+.Ar data
+is an
+.Vt Elf_Data
+descriptor associated with a section of type
+.Dv SHT_SUNW_move .
+Argument
+.Ar ndx
+is the index of the move record being retrieved or updated.
+The class-independent
+.Vt GElf_Move
+structure is described in
+.Xr gelf 3 .
+.Pp
+Function
+.Fn gelf_getmove
+retrieves class-dependent move record at index
+.Ar ndx
+in data buffer
+.Ar data
+and copies it to the destination pointed to by argument
+.Ar move
+after translation to class-independent form.
+.Pp
+Function
+.Fn gelf_update_move
+converts the class-independent move information pointed to
+by argument
+.Ar move
+to class-dependent form, and writes it to the move record at index
+.Ar ndx
+in the data buffer described by argument
+.Ar data .
+Function
+.Fn gelf_update_move
+signals an error if any of the values in the class-independent
+representation exceeds the representable limits of the target
+type.
+.Sh RETURN VALUES
+Function
+.Fn gelf_getmove
+returns the value of argument
+.Ar move
+if successful, or NULL in case of an error.
+Function
+.Fn gelf_update_move
+returns a non-zero value if successful, or zero in case of an error.
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+Arguments
+.Ar data
+or
+.Ar move
+were NULL.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar ndx
+was less than zero or larger than the number of records in the data
+descriptor.
+.It Bq Er ELF_E_ARGUMENT
+Data descriptor
+.Ar data
+was not associated with a section containing move information.
+.It Bq Er ELF_E_RANGE
+A value was not representable in the target type.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_getdata 3 ,
+.Xr elf_getscn 3 ,
+.Xr gelf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_getphdr.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,141 @@
+.\" Copyright (c) 2006-2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: gelf_getphdr.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd October 21, 2007
+.Os
+.Dt GELF_GETPHDR 3
+.Sh NAME
+.Nm elf32_getphdr ,
+.Nm elf64_getphdr ,
+.Nm gelf_getphdr
+.Nd retrieve an ELF program header table
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft "Elf32_Phdr *"
+.Fn elf32_getphdr "Elf *elf"
+.Ft "Elf64_Phdr *"
+.Fn elf64_getphdr "Elf *elf"
+.In gelf.h
+.Ft "GElf_Phdr *"
+.Fn gelf_getphdr "Elf *elf" "int index" "GElf_Phdr *dst"
+.Sh DESCRIPTION
+These functions retrieve and translate ELF program header information
+from an ELF descriptor, if this information exists.
+.Pp
+Functions
+.Fn elf32_getphdr
+and
+.Fn elf64_getphdr
+return a pointer to an array of translated
+.Vt Elf32_Phdr
+and
+.Vt Elf64_Phdr
+descriptors respectively.
+These descriptors are described in
+.Xr elf 5 .
+The number of entries in this array may be determined using the
+.Xr elf_getphnum 3
+function.
+.Pp
+Function
+.Fn gelf_getphdr
+will retrieve the program header table entry at index
+.Ar index
+from ELF descriptor
+.Ar elf.
+The translated program header table entry will be written to the
+address pointed to be argument
+.Ar dst .
+.Pp
+Applications may inform the library of modifications to a program header table entry
+by using the
+.Xr elf_flagphdr 3
+API.
+Applications using the
+.Xr gelf 3
+interface need to use the
+.Xr gelf_update_phdr 3
+API to copy modifications to a program header entry back to the underlying
+ELF descriptor.
+.Sh RETURN VALUES
+The functions a valid pointer if successful, or NULL in case an error
+was encountered.
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was NULL.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was not a descriptor for an ELF object.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar dst
+was NULL.
+.It Bq Er ELF_E_ARGUMENT
+Index
+.Ar index
+was out of range.
+.It Bq Er ELF_E_CLASS
+The class of ELF descriptor
+.Ar elf
+did not match the expected class of the function being called.
+.It Bq Er ELF_E_HEADER
+ELF descriptor
+.Ar elf
+did not possess an executable header.
+.It Bq Er ELF_E_HEADER
+ELF descriptor
+.Ar elf
+had a corrupt executable header.
+.It Bq Er ELF_E_RESOURCE
+An out of memory condition was detected.
+.It Bq Er ELF_E_SECTION
+The ELF descriptor in argument
+.Ar elf
+did not adhere to the conventions used for extended numbering.
+.It Bq Er ELF_VERSION
+ELF descriptor
+.Ar elf
+was of an unsupported version.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf32_getehdr 3 ,
+.Xr elf32_newphdr 3 ,
+.Xr elf64_getehdr 3 ,
+.Xr elf64_newphdr 3 ,
+.Xr elf_flagphdr 3 ,
+.Xr elf_getphnum 3 ,
+.Xr gelf 3 ,
+.Xr gelf_getehdr 3 ,
+.Xr gelf_newphdr 3 ,
+.Xr gelf_update_phdr 3 ,
+.Xr elf 5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_getrel.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,121 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: gelf_getrel.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd August 29, 2006
+.Os
+.Dt GELF_GETREL 3
+.Sh NAME
+.Nm gelf_getrel ,
+.Nm gelf_update_rel
+.Nd read and update ELF relocation entries
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In gelf.h
+.Ft "GElf_Rel *"
+.Fn gelf_getrel "Elf_Data *data" "int ndx" "GElf_Rel *rel"
+.Ft int
+.Fn gelf_update_rel "Elf_Data *data" "int ndx" "GElf_Rel *rel"
+.Sh DESCRIPTION
+These convenience functions are used to retrieve and update class-dependent
+.Vt Elf32_Rel
+or
+.Vt Elf64_Rel
+structures in an ELF object.
+.Pp
+Argument
+.Ar data
+is an
+.Vt Elf_Data
+descriptor associated with a section of type
+.Dv SHT_REL .
+Argument
+.Ar ndx
+is the index of the entry being retrieved or updated.
+The class-independent
+.Vt GElf_Rel
+structure is described in
+.Xr gelf 3 .
+.Pp
+Function
+.Fn gelf_getrel
+retrieves the class-dependent entry at index
+.Ar ndx
+in data buffer
+.Ar data
+and copies it to the destination pointed to by argument
+.Ar rel
+after translation to class-independent form.
+.Pp
+Function
+.Fn gelf_update_rel
+converts the class-independent entry pointed to
+by argument
+.Ar rel
+to class-dependent form, and writes it to the entry at index
+.Ar ndx
+in the data buffer described by argument
+.Ar data .
+Function
+.Fn gelf_update_rel
+signals an error if any of the values in the class-independent
+representation exceeds the representable limits of the target
+type.
+.Sh RETURN VALUES
+Function
+.Fn gelf_getrel
+returns the value of argument
+.Ar rel
+if successful, or NULL in case of an error.
+Function
+.Fn gelf_update_rel
+returns a non-zero value if successful, or zero in case of an error.
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+Arguments
+.Ar data
+or
+.Ar rel
+were NULL.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar ndx
+was less than zero or larger than the number of entries in the data
+descriptor.
+.It Bq Er ELF_E_ARGUMENT
+Data descriptor
+.Ar data
+was not associated with a section of type
+.Dv SHT_REL .
+.It Bq Er ELF_E_RANGE
+A value was not representable in the target type.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_getdata 3 ,
+.Xr elf_getscn 3 ,
+.Xr gelf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_getrela.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,121 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: gelf_getrela.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd August 29, 2006
+.Os
+.Dt GELF_GETRELA 3
+.Sh NAME
+.Nm gelf_getrela ,
+.Nm gelf_update_rela
+.Nd read and update ELF relocation entries with addends
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In gelf.h
+.Ft "GElf_Rela *"
+.Fn gelf_getrela "Elf_Data *data" "int ndx" "GElf_Rela *rela"
+.Ft int
+.Fn gelf_update_rela "Elf_Data *data" "int ndx" "GElf_Rela *rela"
+.Sh DESCRIPTION
+These convenience functions are used to retrieve and update class-dependent
+.Vt Elf32_Rela
+or
+.Vt Elf64_Rela
+structures in an ELF object.
+.Pp
+Argument
+.Ar data
+is an
+.Vt Elf_Data
+descriptor associated with a section of type
+.Dv SHT_RELA .
+Argument
+.Ar ndx
+is the index of the entry being retrieved or updated.
+The class-independent
+.Vt GElf_Rela
+structure is described in
+.Xr gelf 3 .
+.Pp
+Function
+.Fn gelf_getrela
+retrieves the class-dependent entry at index
+.Ar ndx
+in data buffer
+.Ar data
+and copies it to the destination pointed to by argument
+.Ar rela
+after translation to class-independent form.
+.Pp
+Function
+.Fn gelf_update_rela
+converts the class-independent entry pointed to
+by argument
+.Ar rela
+to class-dependent form, and writes it to the entry at index
+.Ar ndx
+in the data buffer described by argument
+.Ar data .
+Function
+.Fn gelf_update_rela
+signals an error if any of the values in the class-independent
+representation exceeds the representable limits of the target
+type.
+.Sh RETURN VALUES
+Function
+.Fn gelf_getrela
+returns the value of argument
+.Ar rela
+if successful, or NULL in case of an error.
+Function
+.Fn gelf_update_rela
+returns a non-zero value if successful, or zero in case of an error.
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+Arguments
+.Ar data
+or
+.Ar rela
+were NULL.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar ndx
+was less than zero or larger than the number of entries in the data
+descriptor.
+.It Bq Er ELF_E_ARGUMENT
+Data descriptor
+.Ar data
+was not associated with a section of type
+.Dv SHT_RELA .
+.It Bq Er ELF_E_RANGE
+A value was not representable in the target type.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_getdata 3 ,
+.Xr elf_getscn 3 ,
+.Xr gelf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_getshdr.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,115 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: gelf_getshdr.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd August 27, 2006
+.Os
+.Dt GELF_GETSHDR 3
+.Sh NAME
+.Nm elf32_getshdr ,
+.Nm elf64_getshdr ,
+.Nm gelf_getshdr
+.Nd retrieve the class-dependent section header
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft "Elf32_Shdr *"
+.Fn elf32_getshdr "Elf_Scn *scn"
+.Ft "Elf64_Shdr *"
+.Fn elf64_getshdr "Elf_Scn *scn"
+.In gelf.h
+.Ft "GElf_Shdr *"
+.Fn gelf_getshdr "Elf_Scn *scn" "GElf_Shdr *shdr"
+.Sh DESCRIPTION
+These functions return a pointer to the ELF Section Header data
+structure associated with section descriptor
+.Ar scn .
+.Pp
+Function
+.Fn elf32_getshdr
+retrieves a pointer to an
+.Vt Elf32_Shdr
+structure.
+Section descriptor
+.Ar scn
+must be associated with an ELF descriptor of class
+.Dv ELFCLASS32 .
+.Pp
+Function
+.Fn elf64_getshdr
+retrieves a pointer to an
+.Vt Elf64_Shdr
+structure.
+Section descriptor
+.Ar scn
+must be associated with an ELF descriptor of class
+.Dv ELFCLASS64 .
+.Pp
+Function
+.Fn gelf_getshdr
+copies the values in the section header associated with argument
+.Ar scn
+to the structure pointed to be argument
+.Ar dst .
+The
+.Vt GElf_Shdr
+data structure is described in
+.Xr gelf 3 .
+.Sh RETURN VALUES
+Functions
+.Fn elf32_getshdr
+and
+.Fn elf64_getshdr
+return a valid pointer to the appropriate section header on success
+or NULL if an error was encountered.
+.Pp
+Function
+.Fn gelf_getshdr
+returns argument
+.Ar dst
+if successful, or NULL if an error was encountered.
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+Arguments
+.Ar scn
+or
+.Ar shdr
+were NULL.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar scn
+was not associated a descriptor for an ELF object.
+.It Bq Er ELF_E_CLASS
+The ELF class associated with the section descriptor
+.Ar scn
+did not match the class expected by the API.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_getscn 3 ,
+.Xr gelf 3 ,
+.Xr gelf_update_shdr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_getsym.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,125 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: gelf_getsym.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd August 29, 2006
+.Os
+.Dt GELF_GETSYM 3
+.Sh NAME
+.Nm gelf_getsym ,
+.Nm gelf_update_sym
+.Nd read and update symbol information
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In gelf.h
+.Ft "GElf_Sym *"
+.Fn gelf_getsym "Elf_Data *data" "int ndx" "GElf_Sym *sym"
+.Ft int
+.Fn gelf_update_sym "Elf_Data *data" "int ndx" "GElf_Sym *sym"
+.Sh DESCRIPTION
+These convenience functions are used to retrieve and update class-dependent
+.Vt Elf32_Sym
+and
+.Vt Elf64_Sym
+structures in an ELF object.
+.Pp
+Argument
+.Ar data
+is an
+.Vt Elf_Data
+descriptor associated with a section of type
+.Dv SHT_SYMTAB ,
+.Dv SHT_DYNSYM
+or
+.Dv SHT_GNU_versym .
+Argument
+.Ar ndx
+is the index of the symbol being retrieved or updated.
+The class-independent
+.Vt GElf_Sym
+structure is described in
+.Xr gelf 3 .
+.Pp
+Function
+.Fn gelf_getsym
+retrieves class-dependent symbol information at index
+.Ar ndx
+in data buffer
+.Ar data
+and copies it to the destination pointed to by argument
+.Ar sym
+after translation to class-independent form.
+.Pp
+Function
+.Fn gelf_update_sym
+converts the class-independent symbol information pointed to
+by argument
+.Ar sym
+to class-dependent form, and writes it to the symbol entry at index
+.Ar ndx
+in the data buffer described by argument
+.Ar data .
+Function
+.Fn gelf_update_sym
+signals an error if any of the values in the class-independent
+representation exceeds the representable limits of the target
+type.
+.Sh RETURN VALUES
+Function
+.Fn gelf_getsym
+returns the value of argument
+.Ar sym
+if successful, or NULL in case of an error.
+Function
+.Fn gelf_update_sym
+returns a non-zero value if successful, or zero in case of an error.
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+Arguments
+.Ar data
+or
+.Ar sym
+were NULL.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar ndx
+was less than zero or larger than the number of symbols in the data
+descriptor.
+.It Bq Er ELF_E_ARGUMENT
+Data descriptor
+.Ar data
+was not associated with a section containing symbol information.
+.It Bq Er ELF_E_RANGE
+A value was not representable in the target type.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_getdata 3 ,
+.Xr elf_getscn 3 ,
+.Xr gelf 3 ,
+.Xr gelf_getsyminfo 3 ,
+.Xr gelf_update_syminfo 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_getsyminfo.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,115 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: gelf_getsyminfo.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd August 29, 2006
+.Os
+.Dt GELF_GETSYMINFO 3
+.Sh NAME
+.Nm gelf_getsyminfo ,
+.Nm gelf_update_syminfo
+.Nd read and update symbol information
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In gelf.h
+.Ft "GElf_Syminfo *"
+.Fn gelf_getsyminfo "Elf_Data *data" "int ndx" "GElf_Syminfo *syminfo"
+.Ft int
+.Fn gelf_update_syminfo "Elf_Data *data" "int ndx" "GElf_Syminfo *syminfo"
+.Sh DESCRIPTION
+These convenience functions are used to retrieve and update class-dependent
+.Vt Elf32_Syminfo
+and
+.Vt Elf64_Syminfo
+records in an ELF object.
+.Pp
+Argument
+.Ar data
+is an
+.Vt Elf_Data
+descriptor associated with a section of type
+.Dv SHT_SUNW_syminfo .
+Argument
+.Ar ndx
+is the index of the record being retrieved or updated.
+The class-independent
+.Vt GElf_Syminfo
+structure is described in
+.Xr gelf 3 .
+.Pp
+Function
+.Fn gelf_getsyminfo
+retrieves class-dependent record at index
+.Ar ndx
+in data buffer
+.Ar data
+and copies it to the destination pointed to by argument
+.Ar syminfo
+after translation to class-independent form.
+.Pp
+Function
+.Fn gelf_update_syminfo
+converts the class-independent record pointed to
+by argument
+.Ar syminfo
+to class-dependent form, and writes it to the record at index
+.Ar ndx
+in the data buffer described by argument
+.Ar data .
+.Sh RETURN VALUES
+Function
+.Fn gelf_getsyminfo
+returns the value of argument
+.Ar syminfo
+if successful, or NULL in case of an error.
+Function
+.Fn gelf_update_syminfo
+returns a non-zero value if successful, or zero in case of an error.
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+Arguments
+.Ar data
+or
+.Ar syminfo
+were NULL.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar ndx
+was less than zero or larger than the number of symbols in the data
+descriptor.
+.It Bq Er ELF_E_ARGUMENT
+Data descriptor
+.Ar data
+was not associated with a section containing symbol information.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_getdata 3 ,
+.Xr elf_getscn 3 ,
+.Xr gelf 3 ,
+.Xr gelf_getsym 3 ,
+.Xr gelf_update_sym 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_getsymshndx.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,162 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: gelf_getsymshndx.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd November 5, 2006
+.Os
+.Dt GELF_GETSYMSHNDX 3
+.Sh NAME
+.Nm gelf_getsymshndx ,
+.Nm gelf_update_symshndx
+.Nd read and update symbol information using extended section indices
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In gelf.h
+.Ft "GElf_Sym *"
+.Fo gelf_getsymshndx
+.Fa "Elf_Data *symdata"
+.Fa "Elf_Data *xndxdata"
+.Fa "int ndx"
+.Fa "GElf_Sym *sym"
+.Fa "Elf32_Word *xndxptr"
+.Fc
+.Ft int
+.Fo gelf_update_symshndx
+.Fa "Elf_Data *symdata"
+.Fa "Elf_Data *xndxdata"
+.Fa "int ndx"
+.Fa "GElf_Sym *sym"
+.Fa "Elf32_Word xndx"
+.Fc
+.Sh DESCRIPTION
+These functions are analogous to
+.Fn gelf_getsym
+and
+.Fn gelf_update_sym
+respectively, but are capable of handling symbol tables using extended
+section numbering.
+.Pp
+Argument
+.Ar symdata
+is an
+.Vt Elf_Data
+descriptor associated with a section of type
+.Dv SHT_SYMTAB .
+Argument
+.Ar xndxdata
+is an
+.Vt Elf_Data
+descriptor associated with a section of type
+.Dv SHT_SYMTAB_SHNDX .
+Argument
+.Ar ndx
+is the index of the symbol table entry being retrieved or updated.
+Argument
+.Ar sym
+is a pointer to a class-independent
+.Vt GElf_Sym
+structure.
+.Vt GElf_Sym
+structures are described in detail in
+.Xr gelf 3 .
+.Pp
+Function
+.Fn gelf_getsymshndx
+retrieves symbol information at index
+.Ar ndx
+from the data descriptor specified by argument
+.Ar symdata
+and stores in class-independent form in argument
+.Ar sym .
+In addition it retrieves the extended section index for the
+symbol from data buffer
+.Ar xndxdata
+and stores it into the location pointed to by argument
+.Ar xndxptr .
+.Pp
+Function
+.Fn gelf_update_symshndx
+updates the underlying symbol table entry in data
+descriptor
+.Ar symdata
+with the information in argument
+.Ar sym .
+In addition it sets the extended section index in
+data buffer
+.Ar xndxdata
+to the value of argument
+.Ar xndx .
+.Sh RETURN VALUES
+Function
+.Fn gelf_getsymshndx
+returns the value of argument
+.Ar sym
+if successful, or NULL in case of an error.
+.Pp
+Function
+.Fn gelf_update_symshndx
+returns a non-zero value if successful, or zero in case of an error.
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+Arguments
+.Ar symdata ,
+.Ar xndxdata ,
+.Ar xndxptr
+or
+.Ar sym
+were NULL.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar ndx
+was less than zero, or too large for either of descriptors
+.Ar symdata
+or
+.Ar xndxdata .
+.It Bq Er ELF_E_ARGUMENT
+Data descriptor
+.Ar symdata
+was not associated with a section of type
+.Dv SHT_SYMTAB .
+.It Bq Er ELF_E_ARGUMENT
+Data descriptor
+.Ar xndxdata
+was not associated with a section of type
+.Dv SHT_SYMTAB_SHNDX .
+.It Bq Er ELF_E_ARGUMENT
+Data descriptor
+.Ar symdata
+and
+.Ar xndxdata
+were associated with different ELF objects.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_getdata 3 ,
+.Xr elf_getscn 3 ,
+.Xr gelf 3 ,
+.Xr gelf_getsym 3 ,
+.Xr gelf_update_sym 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_mips64el.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,82 @@
+/*-
+ * Copyright (c) 2018 John Baldwin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <gelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id$");
+
+int
+_libelf_is_mips64el(Elf *e)
+{
+
+	return (e->e_kind == ELF_K_ELF && e->e_class == ELFCLASS64 &&
+	    e->e_u.e_elf.e_ehdr.e_ehdr64->e_machine == EM_MIPS &&
+	    e->e_u.e_elf.e_ehdr.e_ehdr64->e_ident[EI_DATA] == ELFDATA2LSB);
+}
+
+/*
+ * For MIPS64, the r_info field is actually stored as a 32-bit symbol
+ * index (r_sym) followed by four single-byte fields (r_ssym, r_type3,
+ * r_type2, and r_type).  The byte-swap for the little-endian case
+ * jumbles this incorrectly so compensate.
+ */
+Elf64_Xword
+_libelf_mips64el_r_info_tof(Elf64_Xword r_info)
+{
+	Elf64_Xword new_info;
+	uint8_t ssym, type3, type2, type;
+
+	ssym = r_info >> 24;
+	type3 = r_info >> 16;
+	type2 = r_info >> 8;
+	type = r_info;
+	new_info = r_info >> 32;
+	new_info |= (Elf64_Xword)ssym << 32;
+	new_info |= (Elf64_Xword)type3 << 40;
+	new_info |= (Elf64_Xword)type2 << 48;
+	new_info |= (Elf64_Xword)type << 56;
+	return (new_info);
+}
+
+Elf64_Xword
+_libelf_mips64el_r_info_tom(Elf64_Xword r_info)
+{
+	Elf64_Xword new_info;
+	uint8_t ssym, type3, type2, type;
+
+	ssym = r_info >> 32;
+	type3 = r_info >> 40;
+	type2 = r_info >> 48;
+	type = r_info >> 56;
+	new_info = (r_info & 0xffffffff) << 32;
+	new_info |= (Elf64_Xword)ssym << 24;
+	new_info |= (Elf64_Xword)type3 << 16;
+	new_info |= (Elf64_Xword)type2 << 8;
+	new_info |= (Elf64_Xword)type;
+	return (new_info);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_move.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,159 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <gelf.h>
+#include <limits.h>
+#include <stdint.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: gelf_move.c 3177 2015-03-30 18:19:41Z emaste $");
+
+GElf_Move *
+gelf_getmove(Elf_Data *ed, int ndx, GElf_Move *dst)
+{
+	int ec;
+	Elf *e;
+	size_t msz;
+	Elf_Scn *scn;
+	uint32_t sh_type;
+	Elf32_Move *move32;
+	Elf64_Move *move64;
+	struct _Libelf_Data *d;
+
+	d = (struct _Libelf_Data *) ed;
+
+	if (d == NULL || ndx < 0 || dst == NULL ||
+	    (scn = d->d_scn) == NULL ||
+	    (e = scn->s_elf) == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	ec = e->e_class;
+	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
+
+	if (ec == ELFCLASS32)
+		sh_type = scn->s_shdr.s_shdr32.sh_type;
+	else
+		sh_type = scn->s_shdr.s_shdr64.sh_type;
+
+	if (_libelf_xlate_shtype(sh_type) != ELF_T_MOVE) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	msz = _libelf_msize(ELF_T_MOVE, ec, e->e_version);
+
+	assert(msz > 0);
+	assert(ndx >= 0);
+
+	if (msz * (size_t) ndx >= d->d_data.d_size) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	if (ec == ELFCLASS32) {
+
+		move32 = (Elf32_Move *) d->d_data.d_buf + ndx;
+
+		dst->m_value   = move32->m_value;
+		dst->m_info    = (Elf64_Xword) move32->m_info;
+		dst->m_poffset = (Elf64_Xword) move32->m_poffset;
+		dst->m_repeat  = move32->m_repeat;
+		dst->m_stride = move32->m_stride;
+	} else {
+
+		move64 = (Elf64_Move *) d->d_data.d_buf + ndx;
+
+		*dst = *move64;
+	}
+
+	return (dst);
+}
+
+int
+gelf_update_move(Elf_Data *ed, int ndx, GElf_Move *gm)
+{
+	int ec;
+	Elf *e;
+	size_t msz;
+	Elf_Scn *scn;
+	uint32_t sh_type;
+	Elf32_Move *move32;
+	Elf64_Move *move64;
+	struct _Libelf_Data *d;
+
+	d = (struct _Libelf_Data *) ed;
+
+	if (d == NULL || ndx < 0 || gm == NULL ||
+	    (scn = d->d_scn) == NULL ||
+	    (e = scn->s_elf) == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	ec = e->e_class;
+	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
+
+	if (ec == ELFCLASS32)
+		sh_type = scn->s_shdr.s_shdr32.sh_type;
+	else
+		sh_type = scn->s_shdr.s_shdr64.sh_type;
+
+	if (_libelf_xlate_shtype(sh_type) != ELF_T_MOVE) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	msz = _libelf_msize(ELF_T_MOVE, ec, e->e_version);
+
+	assert(msz > 0);
+	assert(ndx >= 0);
+
+	if (msz * (size_t) ndx >= d->d_data.d_size) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	if (ec == ELFCLASS32) {
+		move32 = (Elf32_Move *) d->d_data.d_buf + ndx;
+
+		move32->m_value  = gm->m_value;
+		LIBELF_COPY_U32(move32, gm, m_info);
+		LIBELF_COPY_U32(move32, gm, m_poffset);
+		move32->m_repeat  = gm->m_repeat;
+		move32->m_stride = gm->m_stride;
+
+	} else {
+		move64 = (Elf64_Move *) d->d_data.d_buf + ndx;
+
+		*move64 = *gm;
+	}
+
+	return (1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_newehdr.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,194 @@
+.\" Copyright (c) 2006-2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: gelf_newehdr.3 3500 2016-12-04 11:08:44Z jkoshy $
+.\"
+.Dd October 22, 2007
+.Os
+.Dt GELF_NEWEHDR 3
+.Sh NAME
+.Nm elf32_newehdr ,
+.Nm elf64_newehdr ,
+.Nm gelf_newehdr
+.Nd retrieve or allocate the object file header
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft "Elf32_Ehdr *"
+.Fn elf32_newehdr "Elf *elf"
+.Ft "Elf64_Ehdr *"
+.Fn elf64_newehdr "Elf *elf"
+.In gelf.h
+.Ft "void *"
+.Fn gelf_newehdr "Elf *elf" "int elfclass"
+.Sh DESCRIPTION
+These functions retrieve the ELF header from the ELF descriptor
+.Ar elf ,
+allocating a new header if needed.
+File data structures are translated to their in-memory representations
+as described in
+.Xr elf 3 .
+.Pp
+Function
+.Fn elf32_newehdr
+returns a pointer to a 32 bit
+.Vt Elf32_Ehdr
+structure.
+Function
+.Fn elf64_newehdr
+returns a pointer to a 64 bit
+.Vt Elf64_Ehdr structure.
+.Pp
+When argument
+.Ar elfclass
+has value
+.Dv ELFCLASS32 ,
+function
+.Fn gelf_newehdr
+returns the value returned by
+.Fn elf32_newehdr "elf" .
+When argument
+.Ar elfclass
+has value
+.Dv ELFCLASS64
+it returns the value returned by
+.Fn elf64_newehdr "elf" .
+.Pp
+If a fresh header structure is allocated, the members of the
+structure are initialized as follows:
+.Bl -tag -width indent
+.It Va "e_ident[EI_MAG0..EI_MAG3]"
+Identification bytes at offsets
+.Dv EI_MAG0 ,
+.Dv EI_MAG1 ,
+.Dv EI_MAG2
+and
+.Dv EI_MAG3
+are set to the ELF signature.
+.It Va "e_ident[EI_CLASS]"
+The identification byte at offset
+.Dv EI_CLASS
+is set to the ELF class associated with the function being called
+or to argument
+.Ar elfclass
+for function
+.Fn gelf_newehdr .
+.It Va "e_ident[EI_DATA]"
+The identification byte at offset
+.Dv EI_DATA
+is set to
+.Dv ELFDATANONE .
+.It Va "e_ident[EI_VERSION]"
+The identification byte at offset
+.Dv EI_VERSION
+is set to the ELF library's operating version set by a prior call to
+.Xr elf_version 3 .
+.It Va e_machine
+is set to
+.Dv EM_NONE .
+.It Va e_type
+is set to
+.Dv ELF_K_NONE .
+.It Va e_version
+is set to the ELF library's operating version set by a prior call to
+.Xr elf_version 3 .
+.El
+.Pp
+Other members of the header are set to zero.
+The application is responsible for changing these values
+as needed before calling
+.Fn elf_update .
+.Pp
+If successful, these three functions set the
+.Dv ELF_F_DIRTY
+flag on ELF descriptor
+.Ar elf .
+.Sh RETURN VALUES
+These functions return a pointer to a translated header descriptor
+if successful, or NULL on failure.
+.Sh COMPATIBILITY
+The
+.Fn gelf_newehdr
+function uses a type of
+.Ft "void *"
+for its returned value.
+This differs from some other implementations of the ELF(3) API, which use an
+.Ft "unsigned long"
+return type.
+.Sh ERRORS
+These functions can fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+The argument
+.Ar elf
+was null.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was not a descriptor for an ELF object.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elfclass
+had an unsupported value.
+.It Bq Er ELF_E_ARGUMENT
+The class of the ELF descriptor
+.Ar elf
+did not match that of the requested operation.
+.It Bq Er ELF_E_ARGUMENT
+For function
+.Fn gelf_newehdr ,
+the class of argument
+.Ar elf
+was not
+.Dv ELFCLASSNONE
+and did not match the argument
+.Ar elfclass .
+.It Bq Er ELF_E_CLASS
+The ELF class of descriptor
+.Ar elf
+did not match that of the API function being called.
+.It Bq Er ELF_E_HEADER
+A malformed ELF header was detected.
+.It Bq Er ELF_E_RESOURCE
+An out of memory condition was detected during execution.
+.It Bq Er ELF_E_SECTION
+The ELF descriptor in argument
+.Ar elf
+did not adhere to the conventions used for extended numbering.
+.It Bq Er ELF_E_VERSION
+The ELF descriptor
+.Ar elf
+had an unsupported ELF version number.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf32_getehdr 3 ,
+.Xr elf64_getehdr 3 ,
+.Xr elf_flagdata 3 ,
+.Xr elf_getident 3 ,
+.Xr elf_update 3 ,
+.Xr elf_version 3 ,
+.Xr gelf 3 ,
+.Xr gelf_getehdr 3 ,
+.Xr elf 5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_newphdr.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,142 @@
+.\" Copyright (c) 2006-2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: gelf_newphdr.3 3500 2016-12-04 11:08:44Z jkoshy $
+.\"
+.Dd October 22, 2007
+.Os
+.Dt GELF_NEWPHDR 3
+.Sh NAME
+.Nm elf32_newphdr ,
+.Nm elf64_newphdr ,
+.Nm gelf_newphdr
+.Nd allocate an ELF program header table
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft "Elf32_Phdr *"
+.Fn elf32_newphdr "Elf *elf" "size_t count"
+.Ft "Elf64_Phdr *"
+.Fn elf64_newphdr "Elf *elf" "size_t count"
+.In gelf.h
+.Ft "void *"
+.Fn gelf_newphdr "Elf *elf" "size_t count"
+.Sh DESCRIPTION
+These functions allocate an ELF Program Header table
+for an ELF descriptor.
+.Vt Elf32_Phdr
+and
+.Vt Elf64_Phdr
+descriptors are described further in
+.Xr elf 5 .
+.Pp
+Functions
+.Fn elf32_newphdr
+and
+.Fn elf64_newphdr
+allocate a table of
+.Ar count
+.Vt Elf32_Phdr
+and
+.Vt Elf64_Phdr
+descriptors respectively,
+discarding any existing program header table
+already present in the ELF descriptor
+.Ar elf .
+A value of zero for argument
+.Ar count
+may be used to delete an existing program header table
+from an ELF descriptor.
+.Pp
+Function
+.Fn gelf_newphdr
+will return a table of
+.Vt Elf32_Phdr
+or
+.Vt Elf64_Phdr
+with
+.Ar count
+elements depending on the ELF class of ELF descriptor
+.Ar elf .
+.Pp
+The functions set the
+.Dv ELF_F_DIRTY
+flag on the program header table.
+All members of the returned array of Phdr structures
+will be initialized to zero.
+.Pp
+After a successful call to these functions, the pointer returned
+by a prior call to
+.Fn elf32_getphdr
+or
+.Fn elf64_getphdr
+on the same descriptor
+.Ar elf
+will no longer be valid.
+.Sh RETURN VALUES
+The functions a valid pointer if successful, or NULL in case an error
+was encountered.
+.Sh COMPATIBILITY
+The
+.Fn gelf_newphdr
+function uses a type of
+.Ft "void *"
+for its returned value.
+This differs from some other implementations of the ELF(3) API, which use an
+.Ft "unsigned long"
+return type.
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was NULL.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was not a descriptor for an ELF object.
+.It Bq Er ELF_E_CLASS
+ELF descriptor
+.Ar elf
+was of an unrecognized class.
+.It Bq Er ELF_E_RESOURCE
+An out of memory condition was detected.
+.It Bq Er ELF_E_SEQUENCE
+An executable header was not allocated for ELF descriptor
+.Ar elf
+before using these APIs.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf32_getphdr 3 ,
+.Xr elf32_newehdr 3 ,
+.Xr elf64_getphdr 3 ,
+.Xr elf64_newehdr 3 ,
+.Xr elf_flagphdr 3 ,
+.Xr elf_getphnum 3 ,
+.Xr gelf 3 ,
+.Xr gelf_getphdr 3 ,
+.Xr gelf_newehdr 3 ,
+.Xr elf 5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_phdr.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,171 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <gelf.h>
+#include <libelf.h>
+#include <limits.h>
+#include <stdint.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: gelf_phdr.c 3576 2017-09-14 02:15:29Z emaste $");
+
+Elf32_Phdr *
+elf32_getphdr(Elf *e)
+{
+	return (_libelf_getphdr(e, ELFCLASS32));
+}
+
+Elf64_Phdr *
+elf64_getphdr(Elf *e)
+{
+	return (_libelf_getphdr(e, ELFCLASS64));
+}
+
+GElf_Phdr *
+gelf_getphdr(Elf *e, int index, GElf_Phdr *d)
+{
+	int ec;
+	Elf32_Ehdr *eh32;
+	Elf64_Ehdr *eh64;
+	Elf32_Phdr *ep32;
+	Elf64_Phdr *ep64;
+	size_t phnum;
+
+	if (d == NULL || e == NULL ||
+	    ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) ||
+	    (e->e_kind != ELF_K_ELF) || index < 0 ||
+	    elf_getphdrnum(e, &phnum) < 0) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	if ((size_t)index >= phnum) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	if (ec == ELFCLASS32) {
+		if ((eh32 = _libelf_ehdr(e, ELFCLASS32, 0)) == NULL ||
+		    ((ep32 = _libelf_getphdr(e, ELFCLASS32)) == NULL))
+			return (NULL);
+
+		ep32 += index;
+
+		d->p_type   = ep32->p_type;
+		d->p_offset = ep32->p_offset;
+		d->p_vaddr  = (Elf64_Addr) ep32->p_vaddr;
+		d->p_paddr  = (Elf64_Addr) ep32->p_paddr;
+		d->p_filesz = (Elf64_Xword) ep32->p_filesz;
+		d->p_memsz  = (Elf64_Xword) ep32->p_memsz;
+		d->p_flags  = ep32->p_flags;
+		d->p_align  = (Elf64_Xword) ep32->p_align;
+
+	} else {
+		if ((eh64 = _libelf_ehdr(e, ELFCLASS64, 0)) == NULL ||
+		    (ep64 = _libelf_getphdr(e, ELFCLASS64)) == NULL)
+			return (NULL);
+
+		ep64 += index;
+
+		*d = *ep64;
+	}
+
+	return (d);
+}
+
+Elf32_Phdr *
+elf32_newphdr(Elf *e, size_t count)
+{
+	return (_libelf_newphdr(e, ELFCLASS32, count));
+}
+
+Elf64_Phdr *
+elf64_newphdr(Elf *e, size_t count)
+{
+	return (_libelf_newphdr(e, ELFCLASS64, count));
+}
+
+void *
+gelf_newphdr(Elf *e, size_t count)
+{
+	if (e == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+	return (_libelf_newphdr(e, e->e_class, count));
+}
+
+int
+gelf_update_phdr(Elf *e, int ndx, GElf_Phdr *s)
+{
+	int ec;
+	size_t phnum;
+	void *ehdr;
+	Elf32_Phdr *ph32;
+	Elf64_Phdr *ph64;
+
+	if (s == NULL || e == NULL || e->e_kind != ELF_K_ELF ||
+	    ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) ||
+	    elf_getphdrnum(e, &phnum) < 0) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	if (e->e_cmd == ELF_C_READ) {
+		LIBELF_SET_ERROR(MODE, 0);
+		return (0);
+	}
+
+	if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL)
+		return (0);
+
+	if (ndx < 0 || (size_t)ndx > phnum) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	(void) elf_flagphdr(e, ELF_C_SET, ELF_F_DIRTY);
+
+	if (ec == ELFCLASS64) {
+		ph64 = e->e_u.e_elf.e_phdr.e_phdr64 + ndx;
+		*ph64 = *s;
+		return (1);
+	}
+
+	ph32 = e->e_u.e_elf.e_phdr.e_phdr32 + ndx;
+
+	ph32->p_type     =  s->p_type;
+	ph32->p_flags    =  s->p_flags;
+	LIBELF_COPY_U32(ph32, s, p_offset);
+	LIBELF_COPY_U32(ph32, s, p_vaddr);
+	LIBELF_COPY_U32(ph32, s, p_paddr);
+	LIBELF_COPY_U32(ph32, s, p_filesz);
+	LIBELF_COPY_U32(ph32, s, p_memsz);
+	LIBELF_COPY_U32(ph32, s, p_align);
+
+	return (1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_rel.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,168 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <gelf.h>
+#include <limits.h>
+#include <stdint.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: gelf_rel.c 3177 2015-03-30 18:19:41Z emaste $");
+
+GElf_Rel *
+gelf_getrel(Elf_Data *ed, int ndx, GElf_Rel *dst)
+{
+	int ec;
+	Elf *e;
+	size_t msz;
+	Elf_Scn *scn;
+	uint32_t sh_type;
+	Elf32_Rel *rel32;
+	Elf64_Rel *rel64;
+	struct _Libelf_Data *d;
+
+	d = (struct _Libelf_Data *) ed;
+
+	if (d == NULL || ndx < 0 || dst == NULL ||
+	    (scn = d->d_scn) == NULL ||
+	    (e = scn->s_elf) == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	ec = e->e_class;
+	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
+
+	if (ec == ELFCLASS32)
+		sh_type = scn->s_shdr.s_shdr32.sh_type;
+	else
+		sh_type = scn->s_shdr.s_shdr64.sh_type;
+
+	if (_libelf_xlate_shtype(sh_type) != ELF_T_REL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	msz = _libelf_msize(ELF_T_REL, ec, e->e_version);
+
+	assert(msz > 0);
+	assert(ndx >= 0);
+
+	if (msz * (size_t) ndx >= d->d_data.d_size) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	if (ec == ELFCLASS32) {
+		rel32 = (Elf32_Rel *) d->d_data.d_buf + ndx;
+
+		dst->r_offset = (Elf64_Addr) rel32->r_offset;
+		dst->r_info   = ELF64_R_INFO(
+		    (Elf64_Xword) ELF32_R_SYM(rel32->r_info),
+		    ELF32_R_TYPE(rel32->r_info));
+
+	} else {
+
+		rel64 = (Elf64_Rel *) d->d_data.d_buf + ndx;
+
+		*dst = *rel64;
+
+		if (_libelf_is_mips64el(e))
+			dst->r_info = _libelf_mips64el_r_info_tom(rel64->r_info);
+	}
+
+	return (dst);
+}
+
+int
+gelf_update_rel(Elf_Data *ed, int ndx, GElf_Rel *dr)
+{
+	int ec;
+	Elf *e;
+	size_t msz;
+	Elf_Scn *scn;
+	uint32_t sh_type;
+	Elf32_Rel *rel32;
+	Elf64_Rel *rel64;
+	struct _Libelf_Data *d;
+
+	d = (struct _Libelf_Data *) ed;
+
+	if (d == NULL || ndx < 0 || dr == NULL ||
+	    (scn = d->d_scn) == NULL ||
+	    (e = scn->s_elf) == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	ec = e->e_class;
+	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
+
+	if (ec == ELFCLASS32)
+		sh_type = scn->s_shdr.s_shdr32.sh_type;
+	else
+		sh_type = scn->s_shdr.s_shdr64.sh_type;
+
+	if (_libelf_xlate_shtype(sh_type) != ELF_T_REL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	msz = _libelf_msize(ELF_T_REL, ec, e->e_version);
+
+	assert(msz > 0);
+	assert(ndx >= 0);
+
+	if (msz * (size_t) ndx >= d->d_data.d_size) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	if (ec == ELFCLASS32) {
+		rel32 = (Elf32_Rel *) d->d_data.d_buf + ndx;
+
+		LIBELF_COPY_U32(rel32, dr, r_offset);
+
+		if (ELF64_R_SYM(dr->r_info) > ELF32_R_SYM(~0UL) ||
+		    ELF64_R_TYPE(dr->r_info) > ELF32_R_TYPE(~0U)) {
+			LIBELF_SET_ERROR(RANGE, 0);
+			return (0);
+		}
+		rel32->r_info = ELF32_R_INFO(
+			(Elf32_Word) ELF64_R_SYM(dr->r_info),
+			(Elf32_Word) ELF64_R_TYPE(dr->r_info));
+	} else {
+		rel64 = (Elf64_Rel *) d->d_data.d_buf + ndx;
+
+		*rel64 = *dr;
+
+		if (_libelf_is_mips64el(e))
+			rel64->r_info = _libelf_mips64el_r_info_tof(dr->r_info);
+	}
+
+	return (1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_rela.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,172 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <gelf.h>
+#include <limits.h>
+#include <stdint.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: gelf_rela.c 3177 2015-03-30 18:19:41Z emaste $");
+
+GElf_Rela *
+gelf_getrela(Elf_Data *ed, int ndx, GElf_Rela *dst)
+{
+	int ec;
+	Elf *e;
+	size_t msz;
+	Elf_Scn *scn;
+	uint32_t sh_type;
+	Elf32_Rela *rela32;
+	Elf64_Rela *rela64;
+	struct _Libelf_Data *d;
+
+	d = (struct _Libelf_Data *) ed;
+
+	if (d == NULL || ndx < 0 || dst == NULL ||
+	    (scn = d->d_scn) == NULL ||
+	    (e = scn->s_elf) == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	ec = e->e_class;
+	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
+
+	if (ec == ELFCLASS32)
+		sh_type = scn->s_shdr.s_shdr32.sh_type;
+	else
+		sh_type = scn->s_shdr.s_shdr64.sh_type;
+
+	if (_libelf_xlate_shtype(sh_type) != ELF_T_RELA) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	msz = _libelf_msize(ELF_T_RELA, ec, e->e_version);
+
+	assert(msz > 0);
+	assert(ndx >= 0);
+
+	if (msz * (size_t) ndx >= d->d_data.d_size) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	if (ec == ELFCLASS32) {
+		rela32 = (Elf32_Rela *) d->d_data.d_buf + ndx;
+
+		dst->r_offset = (Elf64_Addr) rela32->r_offset;
+		dst->r_info   = ELF64_R_INFO(
+		    (Elf64_Xword) ELF32_R_SYM(rela32->r_info),
+		    ELF32_R_TYPE(rela32->r_info));
+		dst->r_addend = (Elf64_Sxword) rela32->r_addend;
+
+	} else {
+
+		rela64 = (Elf64_Rela *) d->d_data.d_buf + ndx;
+
+		*dst = *rela64;
+
+		if (_libelf_is_mips64el(e))
+			dst->r_info =
+			    _libelf_mips64el_r_info_tom(rela64->r_info);
+	}
+
+	return (dst);
+}
+
+int
+gelf_update_rela(Elf_Data *ed, int ndx, GElf_Rela *dr)
+{
+	int ec;
+	Elf *e;
+	size_t msz;
+	Elf_Scn *scn;
+	uint32_t sh_type;
+	Elf32_Rela *rela32;
+	Elf64_Rela *rela64;
+	struct _Libelf_Data *d;
+
+	d = (struct _Libelf_Data *) ed;
+
+	if (d == NULL || ndx < 0 || dr == NULL ||
+	    (scn = d->d_scn) == NULL ||
+	    (e = scn->s_elf) == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	ec = e->e_class;
+	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
+
+	if (ec == ELFCLASS32)
+		sh_type = scn->s_shdr.s_shdr32.sh_type;
+	else
+		sh_type = scn->s_shdr.s_shdr64.sh_type;
+
+	if (_libelf_xlate_shtype(sh_type) != ELF_T_RELA) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	msz = _libelf_msize(ELF_T_RELA, ec, e->e_version);
+
+	assert(msz > 0);
+	assert(ndx >= 0);
+
+	if (msz * (size_t) ndx >= d->d_data.d_size) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	if (ec == ELFCLASS32) {
+		rela32 = (Elf32_Rela *) d->d_data.d_buf + ndx;
+
+		LIBELF_COPY_U32(rela32, dr, r_offset);
+
+		if (ELF64_R_SYM(dr->r_info) > ELF32_R_SYM(~0UL) ||
+		    ELF64_R_TYPE(dr->r_info) > ELF32_R_TYPE(~0U)) {
+			LIBELF_SET_ERROR(RANGE, 0);
+			return (0);
+		}
+		rela32->r_info = ELF32_R_INFO(
+			(Elf32_Word) ELF64_R_SYM(dr->r_info),
+			(Elf32_Word) ELF64_R_TYPE(dr->r_info));
+
+		LIBELF_COPY_S32(rela32, dr, r_addend);
+	} else {
+		rela64 = (Elf64_Rela *) d->d_data.d_buf + ndx;
+
+		*rela64 = *dr;
+
+		if (_libelf_is_mips64el(e))
+			rela64->r_info = _libelf_mips64el_r_info_tof(dr->r_info);
+	}
+
+	return (1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_shdr.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,130 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <gelf.h>
+#include <libelf.h>
+#include <limits.h>
+#include <stdint.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: gelf_shdr.c 3177 2015-03-30 18:19:41Z emaste $");
+
+Elf32_Shdr *
+elf32_getshdr(Elf_Scn *s)
+{
+	return (_libelf_getshdr(s, ELFCLASS32));
+}
+
+Elf64_Shdr *
+elf64_getshdr(Elf_Scn *s)
+{
+	return (_libelf_getshdr(s, ELFCLASS64));
+}
+
+GElf_Shdr *
+gelf_getshdr(Elf_Scn *s, GElf_Shdr *d)
+{
+	int ec;
+	void *sh;
+	Elf32_Shdr *sh32;
+	Elf64_Shdr *sh64;
+
+	if (d == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	if ((sh = _libelf_getshdr(s, ELFCLASSNONE)) == NULL)
+		return (NULL);
+
+	ec = s->s_elf->e_class;
+	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
+
+	if (ec == ELFCLASS32) {
+		sh32 = (Elf32_Shdr *) sh;
+
+		d->sh_name      = sh32->sh_name;
+		d->sh_type      = sh32->sh_type;
+		d->sh_flags     = (Elf64_Xword) sh32->sh_flags;
+		d->sh_addr      = (Elf64_Addr) sh32->sh_addr;
+		d->sh_offset    = (Elf64_Off) sh32->sh_offset;
+		d->sh_size      = (Elf64_Xword) sh32->sh_size;
+		d->sh_link      = sh32->sh_link;
+		d->sh_info      = sh32->sh_info;
+		d->sh_addralign = (Elf64_Xword) sh32->sh_addralign;
+		d->sh_entsize   = (Elf64_Xword) sh32->sh_entsize;
+	} else {
+		sh64 = (Elf64_Shdr *) sh;
+		*d = *sh64;
+	}
+
+	return (d);
+}
+
+int
+gelf_update_shdr(Elf_Scn *scn, GElf_Shdr *s)
+{
+	int ec;
+	Elf *e;
+	Elf32_Shdr *sh32;
+
+
+	if (s == NULL || scn == NULL || (e = scn->s_elf) == NULL ||
+	    e->e_kind != ELF_K_ELF ||
+	    ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	if (e->e_cmd == ELF_C_READ) {
+		LIBELF_SET_ERROR(MODE, 0);
+		return (0);
+	}
+
+	(void) elf_flagscn(scn, ELF_C_SET, ELF_F_DIRTY);
+
+	if (ec == ELFCLASS64) {
+		scn->s_shdr.s_shdr64 = *s;
+		return (1);
+	}
+
+	sh32 = &scn->s_shdr.s_shdr32;
+
+	sh32->sh_name	 =  s->sh_name;
+	sh32->sh_type	 =  s->sh_type;
+	LIBELF_COPY_U32(sh32, s, sh_flags);
+	LIBELF_COPY_U32(sh32, s, sh_addr);
+	LIBELF_COPY_U32(sh32, s, sh_offset);
+	LIBELF_COPY_U32(sh32, s, sh_size);
+	sh32->sh_link	 =  s->sh_link;
+	sh32->sh_info	 =  s->sh_info;
+	LIBELF_COPY_U32(sh32, s, sh_addralign);
+	LIBELF_COPY_U32(sh32, s, sh_entsize);
+
+	return (1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_sym.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,159 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <gelf.h>
+#include <limits.h>
+#include <stdint.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: gelf_sym.c 3177 2015-03-30 18:19:41Z emaste $");
+
+GElf_Sym *
+gelf_getsym(Elf_Data *ed, int ndx, GElf_Sym *dst)
+{
+	int ec;
+	Elf *e;
+	size_t msz;
+	Elf_Scn *scn;
+	uint32_t sh_type;
+	Elf32_Sym *sym32;
+	Elf64_Sym *sym64;
+	struct _Libelf_Data *d;
+
+	d = (struct _Libelf_Data *) ed;
+
+	if (d == NULL || ndx < 0 || dst == NULL ||
+	    (scn = d->d_scn) == NULL ||
+	    (e = scn->s_elf) == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	ec = e->e_class;
+	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
+
+	if (ec == ELFCLASS32)
+		sh_type = scn->s_shdr.s_shdr32.sh_type;
+	else
+		sh_type = scn->s_shdr.s_shdr64.sh_type;
+
+	if (_libelf_xlate_shtype(sh_type) != ELF_T_SYM) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	msz = _libelf_msize(ELF_T_SYM, ec, e->e_version);
+
+	assert(msz > 0);
+	assert(ndx >= 0);
+
+	if (msz * (size_t) ndx >= d->d_data.d_size) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	if (ec == ELFCLASS32) {
+		sym32 = (Elf32_Sym *) d->d_data.d_buf + ndx;
+
+		dst->st_name  = sym32->st_name;
+		dst->st_value = (Elf64_Addr) sym32->st_value;
+		dst->st_size  = (Elf64_Xword) sym32->st_size;
+		dst->st_info  = sym32->st_info;
+		dst->st_other = sym32->st_other;
+		dst->st_shndx = sym32->st_shndx;
+	} else {
+		sym64 = (Elf64_Sym *) d->d_data.d_buf + ndx;
+
+		*dst = *sym64;
+	}
+
+	return (dst);
+}
+
+int
+gelf_update_sym(Elf_Data *ed, int ndx, GElf_Sym *gs)
+{
+	int ec;
+	Elf *e;
+	size_t msz;
+	Elf_Scn *scn;
+	uint32_t sh_type;
+	Elf32_Sym *sym32;
+	Elf64_Sym *sym64;
+	struct _Libelf_Data *d;
+
+	d = (struct _Libelf_Data *) ed;
+
+	if (d == NULL || ndx < 0 || gs == NULL ||
+	    (scn = d->d_scn) == NULL ||
+	    (e = scn->s_elf) == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	ec = e->e_class;
+	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
+
+	if (ec == ELFCLASS32)
+		sh_type = scn->s_shdr.s_shdr32.sh_type;
+	else
+		sh_type = scn->s_shdr.s_shdr64.sh_type;
+
+	if (_libelf_xlate_shtype(sh_type) != ELF_T_SYM) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	msz = _libelf_msize(ELF_T_SYM, ec, e->e_version);
+
+	assert(msz > 0);
+	assert(ndx >= 0);
+
+	if (msz * (size_t) ndx >= d->d_data.d_size) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	if (ec == ELFCLASS32) {
+		sym32 = (Elf32_Sym *) d->d_data.d_buf + ndx;
+
+		sym32->st_name  = gs->st_name;
+		sym32->st_info  = gs->st_info;
+		sym32->st_other = gs->st_other;
+		sym32->st_shndx = gs->st_shndx;
+
+		LIBELF_COPY_U32(sym32, gs, st_value);
+		LIBELF_COPY_U32(sym32, gs, st_size);
+	} else {
+		sym64 = (Elf64_Sym *) d->d_data.d_buf + ndx;
+
+		*sym64 = *gs;
+	}
+
+	return (1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_syminfo.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,152 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <gelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: gelf_syminfo.c 3174 2015-03-27 17:13:41Z emaste $");
+
+GElf_Syminfo *
+gelf_getsyminfo(Elf_Data *ed, int ndx, GElf_Syminfo *dst)
+{
+	int ec;
+	Elf *e;
+	size_t msz;
+	Elf_Scn *scn;
+	uint32_t sh_type;
+	struct _Libelf_Data *d;
+	Elf32_Syminfo *syminfo32;
+	Elf64_Syminfo *syminfo64;
+
+	d = (struct _Libelf_Data *) ed;
+
+	if (d == NULL || ndx < 0 || dst == NULL ||
+	    (scn = d->d_scn) == NULL ||
+	    (e = scn->s_elf) == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	ec = e->e_class;
+	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
+
+	if (ec == ELFCLASS32)
+		sh_type = scn->s_shdr.s_shdr32.sh_type;
+	else
+		sh_type = scn->s_shdr.s_shdr64.sh_type;
+
+	if (_libelf_xlate_shtype(sh_type) != ELF_T_SYMINFO) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	msz = _libelf_msize(ELF_T_SYMINFO, ec, e->e_version);
+
+	assert(msz > 0);
+	assert(ndx >= 0);
+
+	if (msz * (size_t) ndx >= d->d_data.d_size) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	if (ec == ELFCLASS32) {
+
+		syminfo32 = (Elf32_Syminfo *) d->d_data.d_buf + ndx;
+
+		dst->si_boundto = syminfo32->si_boundto;
+		dst->si_flags   = syminfo32->si_flags;
+
+	} else {
+
+		syminfo64 = (Elf64_Syminfo *) d->d_data.d_buf + ndx;
+
+		*dst = *syminfo64;
+	}
+
+	return (dst);
+}
+
+int
+gelf_update_syminfo(Elf_Data *ed, int ndx, GElf_Syminfo *gs)
+{
+	int ec;
+	Elf *e;
+	size_t msz;
+	Elf_Scn *scn;
+	uint32_t sh_type;
+	struct _Libelf_Data *d;
+	Elf32_Syminfo *syminfo32;
+	Elf64_Syminfo *syminfo64;
+
+	d = (struct _Libelf_Data *) ed;
+
+	if (d == NULL || ndx < 0 || gs == NULL ||
+	    (scn = d->d_scn) == NULL ||
+	    (e = scn->s_elf) == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	ec = e->e_class;
+	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
+
+	if (ec == ELFCLASS32)
+		sh_type = scn->s_shdr.s_shdr32.sh_type;
+	else
+		sh_type = scn->s_shdr.s_shdr64.sh_type;
+
+	if (_libelf_xlate_shtype(sh_type) != ELF_T_SYMINFO) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	msz = _libelf_msize(ELF_T_SYMINFO, ec, e->e_version);
+
+	assert(msz > 0);
+	assert(ndx >= 0);
+
+	if (msz * (size_t) ndx >= d->d_data.d_size) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	if (ec == ELFCLASS32) {
+		syminfo32 = (Elf32_Syminfo *) d->d_data.d_buf + ndx;
+
+		syminfo32->si_boundto  = gs->si_boundto;
+		syminfo32->si_flags  = gs->si_flags;
+
+	} else {
+		syminfo64 = (Elf64_Syminfo *) d->d_data.d_buf + ndx;
+
+		*syminfo64 = *gs;
+	}
+
+	return (1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_symshndx.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,137 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <gelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: gelf_symshndx.c 3174 2015-03-27 17:13:41Z emaste $");
+
+GElf_Sym *
+gelf_getsymshndx(Elf_Data *d, Elf_Data *id, int ndx, GElf_Sym *dst,
+    Elf32_Word *shindex)
+{
+	int ec;
+	Elf *e;
+	size_t msz;
+	Elf_Scn *scn;
+	uint32_t sh_type;
+	struct _Libelf_Data *ld, *lid;
+
+	ld = (struct _Libelf_Data *) d;
+	lid = (struct _Libelf_Data *) id;
+
+	if (gelf_getsym(d, ndx, dst) == 0)
+		return (NULL);
+
+	if (lid == NULL || (scn = lid->d_scn) == NULL ||
+	    (e = scn->s_elf) == NULL || (e != ld->d_scn->s_elf) ||
+	    shindex == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	ec = e->e_class;
+	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
+
+	if (ec == ELFCLASS32)
+		sh_type = scn->s_shdr.s_shdr32.sh_type;
+	else
+		sh_type = scn->s_shdr.s_shdr64.sh_type;
+
+	if (_libelf_xlate_shtype(sh_type) != ELF_T_WORD ||
+	   id->d_type != ELF_T_WORD) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	msz = _libelf_msize(ELF_T_WORD, ec, e->e_version);
+
+	assert(msz > 0);
+	assert(ndx >= 0);
+
+	if (msz * (size_t) ndx >= id->d_size) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	*shindex = ((Elf32_Word *) id->d_buf)[ndx];
+
+	return (dst);
+}
+
+int
+gelf_update_symshndx(Elf_Data *d, Elf_Data *id, int ndx, GElf_Sym *gs,
+    Elf32_Word xindex)
+{
+	int ec;
+	Elf *e;
+	size_t msz;
+	Elf_Scn *scn;
+	uint32_t sh_type;
+	struct _Libelf_Data *ld, *lid;
+
+	ld = (struct _Libelf_Data *) d;
+	lid = (struct _Libelf_Data *) id;
+
+	if (gelf_update_sym(d, ndx, gs) == 0)
+		return (0);
+
+	if (lid == NULL || (scn = lid->d_scn) == NULL ||
+	    (e = scn->s_elf) == NULL || (e != ld->d_scn->s_elf)) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	ec = e->e_class;
+	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
+
+	if (ec == ELFCLASS32)
+		sh_type = scn->s_shdr.s_shdr32.sh_type;
+	else
+		sh_type = scn->s_shdr.s_shdr64.sh_type;
+
+	if (_libelf_xlate_shtype(sh_type) != ELF_T_WORD ||
+	    d->d_type != ELF_T_WORD) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	msz = _libelf_msize(ELF_T_WORD, ec, e->e_version);
+
+	assert(msz > 0);
+	assert(ndx >= 0);
+
+	if (msz * (size_t) ndx >= id->d_size) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0);
+	}
+
+	*(((Elf32_Word *) id->d_buf) + ndx) = xindex;
+
+	return (1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_update_ehdr.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,123 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: gelf_update_ehdr.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd August 27, 2006
+.Os
+.Dt GELF_UPDATE_EHDR 3
+.Sh NAME
+.Nm gelf_update_ehdr ,
+.Nm gelf_update_phdr ,
+.Nm gelf_update_shdr
+.Nd update underlying ELF data structures
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In gelf.h
+.Ft int
+.Fn gelf_update_ehdr "Elf *elf" "GElf_Ehdr *ehdr"
+.Ft int
+.Fn gelf_update_phdr "Elf *elf" "int ndx" "GElf_Phdr *phdr"
+.Ft int
+.Fn gelf_update_shdr "Elf_Scn *scn" "GElf_Shdr *shdr"
+.Sh DESCRIPTION
+These functions are used to update ELF data structures on the underlying
+ELF descriptor.
+Class-dependent data structures in the underlying ELF descriptor
+are updated using the data in the class-independent GElf descriptors
+and the underlying ELF data structures are marked
+.Dq dirty .
+The conversion process signals an error if the values being copied
+to the target ELF data structure would exceed representation
+limits.
+GElf descriptors are described in
+.Xr gelf 3 .
+.Pp
+Function
+.Fn gelf_update_ehdr
+updates the ELF Executable Header with the values in the
+class-independent executable header
+.Ar ehdr .
+.Pp
+Function
+.Fn gelf_update_phdr
+updates the ELF Program Header structure at index
+.Ar ndx
+with the values in the class-independent program header
+.Ar phdr .
+.Pp
+Function
+.Fn gelf_update_shdr
+updates the ELF Section Header structure associated with section
+descriptor
+.Ar scn
+with the values in argument
+.Ar shdr .
+.Sh RETURN VALUES
+These functions return a non-zero integer on success, or zero in case
+of an error.
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+Arguments
+.Ar elf ,
+.Ar ehdr ,
+.Ar phdr ,
+.Ar scn ,
+or
+.Ar shdr
+were NULL.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was not a descriptor for an ELF object.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+had an unsupported ELF class.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar ndx
+exceeded the number of entries in the program header table.
+.It Bq Er ELF_E_ARGUMENT
+Section descriptor
+.Ar scn
+was not associated with an ELF descriptor.
+.It Bq Er ELF_E_MODE
+ELF descriptor
+.Ar elf
+was not opened for writing or updating.
+.It Bq Er ELF_E_RESOURCE
+An out of memory condition was detected.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_flagelf 3 ,
+.Xr elf_flagphdr 3 ,
+.Xr elf_flagshdr 3 ,
+.Xr gelf 3 ,
+.Xr gelf_getehdr 3 ,
+.Xr gelf_getphdr 3 ,
+.Xr gelf_getshdr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_xlate.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,79 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <gelf.h>
+#include <libelf.h>
+#include <string.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: gelf_xlate.c 3174 2015-03-27 17:13:41Z emaste $");
+
+Elf_Data *
+elf32_xlatetof(Elf_Data *dst, const Elf_Data *src, unsigned int encoding)
+{
+	return _libelf_xlate(dst, src, encoding, ELFCLASS32, ELF_TOFILE);
+}
+
+Elf_Data *
+elf64_xlatetof(Elf_Data *dst, const Elf_Data *src, unsigned int encoding)
+{
+	return _libelf_xlate(dst, src, encoding, ELFCLASS64, ELF_TOFILE);
+}
+
+Elf_Data *
+elf32_xlatetom(Elf_Data *dst, const Elf_Data *src, unsigned int encoding)
+{
+	return _libelf_xlate(dst, src, encoding, ELFCLASS32, ELF_TOMEMORY);
+}
+
+Elf_Data *
+elf64_xlatetom(Elf_Data *dst, const Elf_Data *src, unsigned int encoding)
+{
+	return _libelf_xlate(dst, src, encoding, ELFCLASS64, ELF_TOMEMORY);
+}
+
+Elf_Data *
+gelf_xlatetom(Elf *e, Elf_Data *dst, const Elf_Data *src,
+    unsigned int encoding)
+{
+	if (e != NULL)
+		return (_libelf_xlate(dst, src, encoding, e->e_class,
+		    ELF_TOMEMORY));
+	LIBELF_SET_ERROR(ARGUMENT, 0);
+	return (NULL);
+}
+
+Elf_Data *
+gelf_xlatetof(Elf *e, Elf_Data *dst, const Elf_Data *src,
+    unsigned int encoding)
+{
+	if (e != NULL)
+		return (_libelf_xlate(dst, src, encoding, e->e_class,
+		    ELF_TOFILE));
+	LIBELF_SET_ERROR(ARGUMENT, 0);
+	return (NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/gelf_xlatetof.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,247 @@
+.\" Copyright (c) 2006,2008 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: gelf_xlatetof.3 189 2008-07-20 10:38:08Z jkoshy $
+.\"
+.Dd July 24, 2006
+.Os
+.Dt GELF_XLATETOF 3
+.Sh NAME
+.Nm elf32_xlate ,
+.Nm elf64_xlate ,
+.Nm gelf_xlate
+.Nd translate data between files and memory
+.Sh LIBRARY
+.Lb libelf
+.Sh SYNOPSIS
+.In libelf.h
+.Ft "Elf_Data *"
+.Fn elf32_xlatetof "Elf_Data *dst" "Elf_Data *src" "unsigned int encode"
+.Ft "Elf_Data *"
+.Fn elf32_xlatetom "Elf_Data *dst" "Elf_Data *src" "unsigned int encode"
+.Ft "Elf_Data *"
+.Fn elf64_xlatetof "Elf_Data *dst" "Elf_Data *src" "unsigned int encode"
+.Ft "Elf_Data *"
+.Fn elf64_xlatetom "Elf_Data *dst" "Elf_Data *src" "unsigned int encode"
+.In gelf.h
+.Ft "Elf_Data *"
+.Fo gelf_xlatetof
+.Fa "Elf *elf"
+.Fa "Elf_Data *dst"
+.Fa "Elf_Data *src"
+.Fa "unsigned int encode"
+.Fc
+.Ft "Elf_Data *"
+.Fo gelf_xlatetom
+.Fa "Elf *elf"
+.Fa "Elf_Data *dst"
+.Fa "Elf_Data *src"
+.Fa "unsigned int encode"
+.Fc
+.Sh DESCRIPTION
+These functions translate between the file and memory representations
+of ELF data structures.
+The in-memory representation of an ELF data structure would confirm to
+the byte ordering and data alignment restrictions dictated by the host
+processor.
+A file representation of the same data structure could use a non-native byte
+ordering and in addition may be laid out differently with the file.
+.Pp
+Functions
+.Fn elf32_xlatetom ,
+.Fn elf64_xlatetom ,
+and
+.Fn gelf_xlatetom
+translate data from file representations to native, in-memory representations.
+Functions
+.Fn elf32_xlatetof ,
+.Fn elf64_xlatetof ,
+and
+.Fn gelf_xlatetof
+translate data from in-memory representations to file representations.
+.Pp
+Argument
+.Ar src
+denotes an
+.Vt Elf_Data
+descriptor describing the source to be translated.
+The following elements of the descriptor need to be set before
+invoking these functions:
+.Bl -hang -offset indent
+.It Va d_buf
+Set to a valid pointer value denoting the beginning of the data area
+to be translated.
+.It Va d_size
+Set to the total size in bytes of the source data area to be
+translated.
+.It Va d_type
+Set to the type of the source data being translated.
+This value is one of the values defined in the
+.Vt Elf_Type
+enumeration.
+The
+.Vt Elf_Type
+enumeration is described in
+.Xr elf 3 .
+.It Va d_version
+Set to the version number of the ELF data structures being
+translated.
+Currently only version
+.Dv EV_CURRENT
+is supported.
+.El
+.Pp
+Argument
+.Ar dst
+describes the destination buffer.
+The following elements of the
+.Vt Elf_Data
+descriptor need to be set before invoking these functions:
+.Bl -hang -offset indent
+.It Va d_buf
+Set to a valid pointer value that denotes the start of the destination
+buffer that will hold translated data.
+This value may be the same as that of the source buffer, in which case
+an in-place conversion will be attempted.
+.It Va d_size
+Set to the size of the destination buffer in bytes.
+This value will be modified if the function call succeeds.
+.It Va d_version
+Set to the desired version number of the destination.
+Currently only version
+.Dv EV_CURRENT
+is supported.
+.El
+.Pp
+These translations routines allow the source and destination buffers
+to coincide, in which case an in-place translation will be done
+if the destination is large enough to hold the translated data.
+Other kinds of overlap between the source and destination buffers
+are not permitted.
+.Pp
+On successful completion of the translation request the following
+fields of the
+.Ar dst
+descriptor would be modified:
+.Bl -hang -offset indent
+.It Va d_size
+Set to the size in bytes of the translated data.
+.It Va d_type
+Set to the
+.Va d_type
+value of the source data descriptor.
+.El
+.Pp
+Argument
+.Ar encode
+specifies the encoding in which the file objects are represented.
+It must be one of:
+.Bl -hang -offset indent
+.It Dv ELFDATANONE
+File objects use the library's native byte ordering.
+.It Dv ELFDATA2LSB
+File objects use a little-endian ordering.
+.It Dv ELFDATA2MSB
+File objects use a big-endian ordering.
+.El
+.Pp
+The functions
+.Fn gelf_xlatetof
+and
+.Fn gelf_xlatetom
+select the appropriate 32 or 64 bit translations based on the class of argument
+.Ar elf .
+.Sh RETURN VALUES
+These functions return argument
+.Ar dst
+if successful, or NULL in case of an error.
+.Sh EXAMPLES
+TODO
+.Sh ERRORS
+These functions may fail with the following errors:
+.Bl -tag -width "[ELF_E_RESOURCE]"
+.It Bq Er ELF_E_ARGUMENT
+One of arguments
+.Ar src ,
+.Ar dst
+or
+.Ar elf
+was NULL.
+.It Bq Er ELF_E_ARGUMENT
+Arguments
+.Ar src
+and
+.Ar dst
+were equal.
+.It Bq Er ELF_E_ARGUMENT
+The desired encoding parameter was not one of
+.Dv ELFDATANONE ,
+.Dv ELFDATA2LSB
+or
+.Dv ELFDATA2MSB .
+.It Bq Er ELF_E_ARGUMENT
+The
+.Ar d_type
+field of argument
+.Ar src
+specified an unsupported type.
+.It Bq Er ELF_E_DATA
+The
+.Ar src
+argument specified a buffer size that was not an integral multiple of
+its underlying type.
+.It Bq Er ELF_E_DATA
+The
+.Ar dst
+argument specified a buffer size that was too small.
+.It Bq Er ELF_E_DATA
+Argument
+.Ar dst
+specified a destination buffer that overlaps with the source
+buffer.
+.It Bq Er ELF_E_DATA
+The destination buffer for a conversion to memory had an alignment
+inappropriate for the underlying ELF type.
+.It Bq Er ELF_E_DATA
+The source buffer for a conversion to file had an alignment
+inappropriate for the underlying ELF type.
+.It Bq Er ELF_E_UNIMPL
+The version numbers for arguments
+.Ar dst
+and
+.Ar src
+were not identical.
+.It Bq Er ELF_E_UNIMPL
+The argument
+.Ar src
+requested conversion for a type which is not currently
+supported.
+.It Bq Er ELF_E_VERSION
+Argument
+.Ar src
+specified an unsupported version number.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_getdata 3 ,
+.Xr gelf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/libelf.h	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,256 @@
+/*-
+ * Copyright (c) 2006,2008-2010 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: libelf.h 3174 2015-03-27 17:13:41Z emaste $
+ */
+
+#ifndef	_LIBELF_H_
+#define	_LIBELF_H_
+
+#include <sys/types.h>
+#include <sys/elf32.h>
+#include <sys/elf64.h>
+
+/* Library private data structures */
+typedef struct _Elf Elf;
+typedef struct _Elf_Scn Elf_Scn;
+
+/* File types */
+typedef enum {
+	ELF_K_NONE = 0,
+	ELF_K_AR,	/* `ar' archives */
+	ELF_K_COFF,	/* COFF files (unsupported) */
+	ELF_K_ELF,	/* ELF files */
+	ELF_K_NUM
+} Elf_Kind;
+
+#define	ELF_K_FIRST	ELF_K_NONE
+#define	ELF_K_LAST	ELF_K_NUM
+
+/* Data types */
+typedef enum {
+	ELF_T_ADDR,
+	ELF_T_BYTE,
+	ELF_T_CAP,
+	ELF_T_DYN,
+	ELF_T_EHDR,
+	ELF_T_HALF,
+	ELF_T_LWORD,
+	ELF_T_MOVE,
+	ELF_T_MOVEP,
+	ELF_T_NOTE,
+	ELF_T_OFF,
+	ELF_T_PHDR,
+	ELF_T_REL,
+	ELF_T_RELA,
+	ELF_T_SHDR,
+	ELF_T_SWORD,
+	ELF_T_SXWORD,
+	ELF_T_SYMINFO,
+	ELF_T_SYM,
+	ELF_T_VDEF,
+	ELF_T_VNEED,
+	ELF_T_WORD,
+	ELF_T_XWORD,
+	ELF_T_GNUHASH,	/* GNU style hash tables. */
+	ELF_T_NUM
+} Elf_Type;
+
+#define	ELF_T_FIRST	ELF_T_ADDR
+#define	ELF_T_LAST	ELF_T_GNUHASH
+
+/* Commands */
+typedef enum {
+	ELF_C_NULL = 0,
+	ELF_C_CLR,
+	ELF_C_FDDONE,
+	ELF_C_FDREAD,
+	ELF_C_RDWR,
+	ELF_C_READ,
+	ELF_C_SET,
+	ELF_C_WRITE,
+	ELF_C_NUM
+} Elf_Cmd;
+
+#define	ELF_C_FIRST	ELF_C_NULL
+#define	ELF_C_LAST	ELF_C_NUM
+
+/*
+ * An `Elf_Data' structure describes data in an
+ * ELF section.
+ */
+typedef struct _Elf_Data {
+	/*
+	 * `Public' members that are part of the ELF(3) API.
+	 */
+	uint64_t	d_align;
+	void		*d_buf;
+	uint64_t	d_off;
+	uint64_t	d_size;
+	Elf_Type	d_type;
+	unsigned int	d_version;
+} Elf_Data;
+
+/*
+ * An `Elf_Arhdr' structure describes an archive
+ * header.
+ */
+typedef struct {
+	time_t		ar_date;
+	char		*ar_name;	/* archive member name */
+	gid_t		ar_gid;
+	mode_t		ar_mode;
+	char		*ar_rawname;	/* 'raw' member name */
+	size_t		ar_size;
+	uid_t		ar_uid;
+
+	/*
+	 * Members that are not part of the public API.
+	 */
+	unsigned int	ar_flags;
+} Elf_Arhdr;
+
+/*
+ * An `Elf_Arsym' describes an entry in the archive
+ * symbol table.
+ */
+typedef struct {
+	off_t		as_off;		/* byte offset to member's header */
+	unsigned long	as_hash;	/* elf_hash() value for name */
+	char		*as_name; 	/* null terminated symbol name */
+} Elf_Arsym;
+
+/*
+ * Error numbers.
+ */
+
+enum Elf_Error {
+	ELF_E_NONE,	/* No error */
+	ELF_E_ARCHIVE,	/* Malformed ar(1) archive */
+	ELF_E_ARGUMENT,	/* Invalid argument */
+	ELF_E_CLASS,	/* Mismatched ELF class */
+	ELF_E_DATA,	/* Invalid data descriptor */
+	ELF_E_HEADER,	/* Missing or malformed ELF header */
+	ELF_E_IO,	/* I/O error */
+	ELF_E_LAYOUT,	/* Layout constraint violation */
+	ELF_E_MODE,	/* Wrong mode for ELF descriptor */
+	ELF_E_RANGE,	/* Value out of range */
+	ELF_E_RESOURCE,	/* Resource exhaustion */
+	ELF_E_SECTION,	/* Invalid section descriptor */
+	ELF_E_SEQUENCE,	/* API calls out of sequence */
+	ELF_E_UNIMPL,	/* Feature is unimplemented */
+	ELF_E_VERSION,	/* Unknown API version */
+	ELF_E_NUM	/* Max error number */
+};
+
+/*
+ * Flags defined by the API.
+ */
+
+#define	ELF_F_LAYOUT	0x001U	/* application will layout the file */
+#define	ELF_F_DIRTY	0x002U	/* a section or ELF file is dirty */
+
+/* ELF(3) API extensions. */
+#define	ELF_F_ARCHIVE	   0x100U /* archive creation */
+#define	ELF_F_ARCHIVE_SYSV 0x200U /* SYSV style archive */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+Elf		*elf_begin(int _fd, Elf_Cmd _cmd, Elf *_elf);
+int		elf_cntl(Elf *_elf, Elf_Cmd _cmd);
+int		elf_end(Elf *_elf);
+const char	*elf_errmsg(int _error);
+int		elf_errno(void);
+void		elf_fill(int _fill);
+unsigned int	elf_flagarhdr(Elf_Arhdr *_arh, Elf_Cmd _cmd,
+			unsigned int _flags);
+unsigned int	elf_flagdata(Elf_Data *_data, Elf_Cmd _cmd,
+			unsigned int _flags);
+unsigned int	elf_flagehdr(Elf *_elf, Elf_Cmd _cmd, unsigned int _flags);
+unsigned int	elf_flagelf(Elf *_elf, Elf_Cmd _cmd, unsigned int _flags);
+unsigned int	elf_flagphdr(Elf *_elf, Elf_Cmd _cmd, unsigned int _flags);
+unsigned int	elf_flagscn(Elf_Scn *_scn, Elf_Cmd _cmd, unsigned int _flags);
+unsigned int	elf_flagshdr(Elf_Scn *_scn, Elf_Cmd _cmd, unsigned int _flags);
+Elf_Arhdr	*elf_getarhdr(Elf *_elf);
+Elf_Arsym	*elf_getarsym(Elf *_elf, size_t *_ptr);
+off_t		elf_getbase(Elf *_elf);
+Elf_Data	*elf_getdata(Elf_Scn *, Elf_Data *);
+char		*elf_getident(Elf *_elf, size_t *_ptr);
+int		elf_getphdrnum(Elf *_elf, size_t *_dst);
+int		elf_getphnum(Elf *_elf, size_t *_dst);	/* Deprecated */
+Elf_Scn		*elf_getscn(Elf *_elf, size_t _index);
+int		elf_getshdrnum(Elf *_elf, size_t *_dst);
+int		elf_getshnum(Elf *_elf, size_t *_dst);	/* Deprecated */
+int		elf_getshdrstrndx(Elf *_elf, size_t *_dst);
+int		elf_getshstrndx(Elf *_elf, size_t *_dst); /* Deprecated */
+unsigned long	elf_hash(const char *_name);
+Elf_Kind	elf_kind(Elf *_elf);
+Elf		*elf_memory(char *_image, size_t _size);
+size_t		elf_ndxscn(Elf_Scn *_scn);
+Elf_Data	*elf_newdata(Elf_Scn *_scn);
+Elf_Scn		*elf_newscn(Elf *_elf);
+Elf_Scn		*elf_nextscn(Elf *_elf, Elf_Scn *_scn);
+Elf_Cmd		elf_next(Elf *_elf);
+Elf		*elf_open(int _fd);
+Elf		*elf_openmemory(char *_image, size_t _size);
+off_t		elf_rand(Elf *_elf, off_t _off);
+Elf_Data	*elf_rawdata(Elf_Scn *_scn, Elf_Data *_data);
+char		*elf_rawfile(Elf *_elf, size_t *_size);
+int		elf_setshstrndx(Elf *_elf, size_t _shnum);
+char		*elf_strptr(Elf *_elf, size_t _section, size_t _offset);
+off_t		elf_update(Elf *_elf, Elf_Cmd _cmd);
+unsigned int	elf_version(unsigned int _version);
+
+long		elf32_checksum(Elf *_elf);
+size_t		elf32_fsize(Elf_Type _type, size_t _count,
+			unsigned int _version);
+Elf32_Ehdr	*elf32_getehdr(Elf *_elf);
+Elf32_Phdr	*elf32_getphdr(Elf *_elf);
+Elf32_Shdr	*elf32_getshdr(Elf_Scn *_scn);
+Elf32_Ehdr	*elf32_newehdr(Elf *_elf);
+Elf32_Phdr	*elf32_newphdr(Elf *_elf, size_t _count);
+Elf_Data	*elf32_xlatetof(Elf_Data *_dst, const Elf_Data *_src,
+			unsigned int _enc);
+Elf_Data	*elf32_xlatetom(Elf_Data *_dst, const Elf_Data *_src,
+			unsigned int _enc);
+
+long		elf64_checksum(Elf *_elf);
+size_t		elf64_fsize(Elf_Type _type, size_t _count,
+			unsigned int _version);
+Elf64_Ehdr	*elf64_getehdr(Elf *_elf);
+Elf64_Phdr	*elf64_getphdr(Elf *_elf);
+Elf64_Shdr	*elf64_getshdr(Elf_Scn *_scn);
+Elf64_Ehdr	*elf64_newehdr(Elf *_elf);
+Elf64_Phdr	*elf64_newphdr(Elf *_elf, size_t _count);
+Elf_Data	*elf64_xlatetof(Elf_Data *_dst, const Elf_Data *_src,
+			unsigned int _enc);
+Elf_Data	*elf64_xlatetom(Elf_Data *_dst, const Elf_Data *_src,
+			unsigned int _enc);
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _LIBELF_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/libelf_align.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,135 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: libelf_align.c 3174 2015-03-27 17:13:41Z emaste $");
+
+struct align {
+	unsigned int a32;
+	unsigned int a64;
+};
+
+#ifdef	__GNUC__
+#define	MALIGN(N)	{					\
+		.a32 = __alignof__(Elf32_##N),			\
+		.a64 = __alignof__(Elf64_##N)			\
+	}
+#define	MALIGN64(V)	  {					\
+		.a32 = 0,					\
+		.a64 = __alignof__(Elf64_##V)			\
+	}
+#define	MALIGN_WORD()	{					\
+		.a32 = __alignof__(int32_t),			\
+		.a64 = __alignof__(int64_t)			\
+	    }
+#else
+#error	Need the __alignof__ builtin.
+#endif
+#define	UNSUPPORTED()	{					\
+		.a32 = 0,					\
+		.a64 = 0					\
+	}
+
+static struct align malign[ELF_T_NUM] = {
+	[ELF_T_ADDR]	= MALIGN(Addr),
+	[ELF_T_BYTE]	= { .a32 = 1, .a64 = 1 },
+	[ELF_T_CAP]	= MALIGN(Cap),
+	[ELF_T_DYN]	= MALIGN(Dyn),
+	[ELF_T_EHDR]	= MALIGN(Ehdr),
+	[ELF_T_HALF]	= MALIGN(Half),
+	[ELF_T_LWORD]	= MALIGN(Lword),
+	[ELF_T_MOVE]	= MALIGN(Move),
+	[ELF_T_MOVEP] 	= UNSUPPORTED(),
+	[ELF_T_NOTE]	= MALIGN(Nhdr),
+	[ELF_T_OFF]	= MALIGN(Off),
+	[ELF_T_PHDR]	= MALIGN(Phdr),
+	[ELF_T_REL]	= MALIGN(Rel),
+	[ELF_T_RELA]	= MALIGN(Rela),
+	[ELF_T_SHDR]	= MALIGN(Shdr),
+	[ELF_T_SWORD]	= MALIGN(Sword),
+	[ELF_T_SXWORD]	= MALIGN64(Sxword),
+	[ELF_T_SYM]	= MALIGN(Sym),
+	[ELF_T_SYMINFO]	= MALIGN(Syminfo),
+	[ELF_T_VDEF]	= MALIGN(Verdef),
+	[ELF_T_VNEED]	= MALIGN(Verneed),
+	[ELF_T_WORD]	= MALIGN(Word),
+	[ELF_T_XWORD]	= MALIGN64(Xword),
+	[ELF_T_GNUHASH] = MALIGN_WORD()
+};
+
+unsigned int
+_libelf_malign(Elf_Type t, int elfclass)
+{
+	if (t >= ELF_T_NUM || (int) t < 0)
+		return (0);
+
+	return (elfclass == ELFCLASS32 ? malign[t].a32 :
+	    malign[t].a64);
+}
+
+#define	FALIGN(A32,A64)	{ .a32 = (A32), .a64 = (A64) }
+
+static struct align falign[ELF_T_NUM] = {
+	[ELF_T_ADDR]	= FALIGN(4,8),
+	[ELF_T_BYTE]	= FALIGN(1,1),
+	[ELF_T_CAP]	= FALIGN(4,8),
+	[ELF_T_DYN]	= FALIGN(4,8),
+	[ELF_T_EHDR]	= FALIGN(4,8),
+	[ELF_T_HALF]	= FALIGN(2,2),
+	[ELF_T_LWORD]	= FALIGN(8,8),
+	[ELF_T_MOVE]	= FALIGN(8,8),
+	[ELF_T_MOVEP] 	= UNSUPPORTED(),
+	[ELF_T_NOTE]	= FALIGN(1,1),
+	[ELF_T_OFF]	= FALIGN(4,8),
+	[ELF_T_PHDR]	= FALIGN(4,8),
+	[ELF_T_REL]	= FALIGN(4,8),
+	[ELF_T_RELA]	= FALIGN(4,8),
+	[ELF_T_SHDR]	= FALIGN(4,8),
+	[ELF_T_SWORD]	= FALIGN(4,4),
+	[ELF_T_SXWORD]	= FALIGN(0,8),
+	[ELF_T_SYM]	= FALIGN(4,8),
+	[ELF_T_SYMINFO]	= FALIGN(2,2),
+	[ELF_T_VDEF]	= FALIGN(4,4),
+	[ELF_T_VNEED]	= FALIGN(4,4),
+	[ELF_T_WORD]	= FALIGN(4,4),
+	[ELF_T_XWORD]	= FALIGN(0,8),
+	[ELF_T_GNUHASH] = FALIGN(4,8)
+};
+
+unsigned int
+_libelf_falign(Elf_Type t, int elfclass)
+{
+	if (t >= ELF_T_NUM || (int) t < 0)
+		return (0);
+
+	return (elfclass == ELFCLASS32 ? falign[t].a32 :
+	    falign[t].a64);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/libelf_allocate.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,210 @@
+/*-
+ * Copyright (c) 2006,2008,2010 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Internal APIs
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <libelf.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: libelf_allocate.c 3174 2015-03-27 17:13:41Z emaste $");
+
+Elf *
+_libelf_allocate_elf(void)
+{
+	Elf *e;
+
+	if ((e = malloc(sizeof(*e))) == NULL) {
+		LIBELF_SET_ERROR(RESOURCE, errno);
+		return NULL;
+	}
+
+	e->e_activations = 1;
+	e->e_hdr.e_rawhdr = NULL;
+	e->e_byteorder   = ELFDATANONE;
+	e->e_class       = ELFCLASSNONE;
+	e->e_cmd         = ELF_C_NULL;
+	e->e_fd          = -1;
+	e->e_flags	 = 0;
+	e->e_kind        = ELF_K_NONE;
+	e->e_parent      = NULL;
+	e->e_rawfile     = NULL;
+	e->e_rawsize     = 0;
+	e->e_version     = LIBELF_PRIVATE(version);
+
+	(void) memset(&e->e_u, 0, sizeof(e->e_u));
+
+	return (e);
+}
+
+void
+_libelf_init_elf(Elf *e, Elf_Kind kind)
+{
+	assert(e != NULL);
+	assert(e->e_kind == ELF_K_NONE);
+
+	e->e_kind = kind;
+
+	switch (kind) {
+	case ELF_K_ELF:
+		STAILQ_INIT(&e->e_u.e_elf.e_scn);
+		break;
+	default:
+		break;
+	}
+}
+
+#define	FREE(P)		do {				\
+		if (P)					\
+			free(P);			\
+	} while (0)
+
+
+Elf *
+_libelf_release_elf(Elf *e)
+{
+	Elf_Arhdr *arh;
+
+	switch (e->e_kind) {
+	case ELF_K_AR:
+		FREE(e->e_u.e_ar.e_symtab);
+		break;
+
+	case ELF_K_ELF:
+		switch (e->e_class) {
+		case ELFCLASS32:
+			FREE(e->e_u.e_elf.e_ehdr.e_ehdr32);
+			FREE(e->e_u.e_elf.e_phdr.e_phdr32);
+			break;
+		case ELFCLASS64:
+			FREE(e->e_u.e_elf.e_ehdr.e_ehdr64);
+			FREE(e->e_u.e_elf.e_phdr.e_phdr64);
+			break;
+		}
+
+		assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn));
+
+		if (e->e_flags & LIBELF_F_AR_HEADER) {
+			arh = e->e_hdr.e_arhdr;
+			FREE(arh->ar_name);
+			FREE(arh->ar_rawname);
+			free(arh);
+		}
+
+		break;
+
+	default:
+		break;
+	}
+
+	free(e);
+
+	return (NULL);
+}
+
+struct _Libelf_Data *
+_libelf_allocate_data(Elf_Scn *s)
+{
+	struct _Libelf_Data *d;
+
+	if ((d = calloc((size_t) 1, sizeof(*d))) == NULL) {
+		LIBELF_SET_ERROR(RESOURCE, 0);
+		return (NULL);
+	}
+
+	d->d_scn = s;
+
+	return (d);
+}
+
+struct _Libelf_Data *
+_libelf_release_data(struct _Libelf_Data *d)
+{
+
+	if (d->d_flags & LIBELF_F_DATA_MALLOCED)
+		free(d->d_data.d_buf);
+
+	free(d);
+
+	return (NULL);
+}
+
+Elf_Scn *
+_libelf_allocate_scn(Elf *e, size_t ndx)
+{
+	Elf_Scn *s;
+
+	if ((s = calloc((size_t) 1, sizeof(Elf_Scn))) == NULL) {
+		LIBELF_SET_ERROR(RESOURCE, errno);
+		return (NULL);
+	}
+
+	s->s_elf = e;
+	s->s_ndx = ndx;
+
+	STAILQ_INIT(&s->s_data);
+	STAILQ_INIT(&s->s_rawdata);
+
+	STAILQ_INSERT_TAIL(&e->e_u.e_elf.e_scn, s, s_next);
+
+	return (s);
+}
+
+Elf_Scn *
+_libelf_release_scn(Elf_Scn *s)
+{
+	Elf *e;
+	struct _Libelf_Data *d, *td;
+
+	assert(s != NULL);
+
+	STAILQ_FOREACH_SAFE(d, &s->s_data, d_next, td) {
+		STAILQ_REMOVE(&s->s_data, d, _Libelf_Data, d_next);
+		d = _libelf_release_data(d);
+	}
+
+	STAILQ_FOREACH_SAFE(d, &s->s_rawdata, d_next, td) {
+		assert((d->d_flags & LIBELF_F_DATA_MALLOCED) == 0);
+		STAILQ_REMOVE(&s->s_rawdata, d, _Libelf_Data, d_next);
+		d = _libelf_release_data(d);
+	}
+
+	e = s->s_elf;
+
+	assert(e != NULL);
+
+	STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn, s_next);
+
+	free(s);
+
+	return (NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/libelf_ar.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,466 @@
+/*-
+ * Copyright (c) 2006,2008,2010 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS `AS IS' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <libelf.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "_libelf.h"
+#include "_libelf_ar.h"
+
+ELFTC_VCSID("$Id: libelf_ar.c 3446 2016-05-03 01:31:17Z emaste $");
+
+#define	LIBELF_NALLOC_SIZE	16
+
+/*
+ * `ar' archive handling.
+ *
+ * `ar' archives start with signature `ARMAG'.  Each archive member is
+ * preceded by a header containing meta-data for the member.  This
+ * header is described in <ar.h> (struct ar_hdr).  The header always
+ * starts on an even address.  File data is padded with "\n"
+ * characters to keep this invariant.
+ *
+ * Special considerations for `ar' archives:
+ *
+ * There are two variants of the `ar' archive format: traditional BSD
+ * and SVR4.  These differ in the way long file names are treated, and
+ * in the layout of the archive symbol table.
+ *
+ * The `ar' header only has space for a 16 character file name.
+ *
+ * In the SVR4 format, file names are terminated with a '/', so this
+ * effectively leaves 15 characters for the actual file name.  Longer
+ * file names stored in a separate 'string table' and referenced
+ * indirectly from the name field.  The string table itself appears as
+ * an archive member with name "// ".  An `indirect' file name in an
+ * `ar' header matches the pattern "/[0-9]*". The digits form a
+ * decimal number that corresponds to a byte offset into the string
+ * table where the actual file name of the object starts.  Strings in
+ * the string table are padded to start on even addresses.
+ *
+ * In the BSD format, file names can be up to 16 characters.  File
+ * names shorter than 16 characters are padded to 16 characters using
+ * (ASCII) space characters.  File names with embedded spaces and file
+ * names longer than 16 characters are stored immediately after the
+ * archive header and the name field set to a special indirect name
+ * matching the pattern "#1/[0-9]+".  The digits form a decimal number
+ * that corresponds to the actual length of the file name following
+ * the archive header.  The content of the archive member immediately
+ * follows the file name, and the size field of the archive member
+ * holds the sum of the sizes of the member and of the appended file
+ * name.
+ *
+ * Archives may also have a symbol table (see ranlib(1)), mapping
+ * program symbols to object files inside the archive.
+ *
+ * In the SVR4 format, a symbol table uses a file name of "/ " in its
+ * archive header.  The symbol table is structured as:
+ *  - a 4-byte count of entries stored as a binary value, MSB first
+ *  - 'n' 4-byte offsets, stored as binary values, MSB first
+ *  - 'n' NUL-terminated strings, for ELF symbol names, stored unpadded.
+ *
+ * In the BSD format, the symbol table uses a file name of "__.SYMDEF".
+ * It is structured as two parts:
+ *  - The first part is an array of "ranlib" structures preceded by
+ *    the size of the array in bytes.  Each "ranlib" structure
+ *    describes one symbol.  Each structure contains an offset into
+ *    the string table for the symbol name, and a file offset into the
+ *    archive for the member defining the symbol.
+ *  - The second part is a string table containing NUL-terminated
+ *    strings, preceded by the size of the string table in bytes.
+ *
+ * If the symbol table and string table are is present in an archive
+ * they must be the very first objects and in that order.
+ */
+
+
+/*
+ * Retrieve an archive header descriptor.
+ */
+
+Elf_Arhdr *
+_libelf_ar_gethdr(Elf *e)
+{
+	Elf *parent;
+	Elf_Arhdr *eh;
+	char *namelen;
+	size_t n, nlen;
+	struct ar_hdr *arh;
+
+	if ((parent = e->e_parent) == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	assert((e->e_flags & LIBELF_F_AR_HEADER) == 0);
+
+	arh = (struct ar_hdr *) (uintptr_t) e->e_hdr.e_rawhdr;
+
+	assert((uintptr_t) arh >= (uintptr_t) parent->e_rawfile + SARMAG);
+	assert((uintptr_t) arh <= (uintptr_t) parent->e_rawfile +
+	    parent->e_rawsize - sizeof(struct ar_hdr));
+
+	if ((eh = malloc(sizeof(Elf_Arhdr))) == NULL) {
+		LIBELF_SET_ERROR(RESOURCE, 0);
+		return (NULL);
+	}
+
+	e->e_hdr.e_arhdr = eh;
+	e->e_flags |= LIBELF_F_AR_HEADER;
+
+	eh->ar_name = eh->ar_rawname = NULL;
+
+	if ((eh->ar_name = _libelf_ar_get_translated_name(arh, parent)) ==
+	    NULL)
+		goto error;
+
+	if (_libelf_ar_get_number(arh->ar_uid, sizeof(arh->ar_uid), 10,
+	    &n) == 0)
+		goto error;
+	eh->ar_uid = (uid_t) n;
+
+	if (_libelf_ar_get_number(arh->ar_gid, sizeof(arh->ar_gid), 10,
+	    &n) == 0)
+		goto error;
+	eh->ar_gid = (gid_t) n;
+
+	if (_libelf_ar_get_number(arh->ar_mode, sizeof(arh->ar_mode), 8,
+	    &n) == 0)
+		goto error;
+	eh->ar_mode = (mode_t) n;
+
+	if (_libelf_ar_get_number(arh->ar_size, sizeof(arh->ar_size), 10,
+	    &n) == 0)
+		goto error;
+
+	/*
+	 * Get the true size of the member if extended naming is being used.
+	 */
+	if (IS_EXTENDED_BSD_NAME(arh->ar_name)) {
+		namelen = arh->ar_name +
+		    LIBELF_AR_BSD_EXTENDED_NAME_PREFIX_SIZE;
+		if (_libelf_ar_get_number(namelen, sizeof(arh->ar_name) -
+		    LIBELF_AR_BSD_EXTENDED_NAME_PREFIX_SIZE, 10, &nlen) == 0)
+			goto error;
+		n -= nlen;
+	}
+
+	eh->ar_size = n;
+
+	if ((eh->ar_rawname = _libelf_ar_get_raw_name(arh)) == NULL)
+		goto error;
+
+	eh->ar_flags = 0;
+
+	return (eh);
+
+ error:
+	if (eh) {
+		if (eh->ar_name)
+			free(eh->ar_name);
+		if (eh->ar_rawname)
+			free(eh->ar_rawname);
+		free(eh);
+	}
+
+	e->e_flags &= ~LIBELF_F_AR_HEADER;
+	e->e_hdr.e_rawhdr = (unsigned char *) arh;
+
+	return (NULL);
+}
+
+Elf *
+_libelf_ar_open_member(int fd, Elf_Cmd c, Elf *elf)
+{
+	Elf *e;
+	off_t next;
+	size_t nsz, sz;
+	struct ar_hdr *arh;
+	char *member, *namelen;
+
+	assert(elf->e_kind == ELF_K_AR);
+
+	next = elf->e_u.e_ar.e_next;
+
+	/*
+	 * `next' is only set to zero by elf_next() when the last
+	 * member of an archive is processed.
+	 */
+	if (next == (off_t) 0)
+		return (NULL);
+
+	assert((next & 1) == 0);
+
+	arh = (struct ar_hdr *) (elf->e_rawfile + next);
+
+	/*
+	 * Retrieve the size of the member.
+	 */
+	if (_libelf_ar_get_number(arh->ar_size, sizeof(arh->ar_size), 10,
+	    &sz) == 0) {
+		LIBELF_SET_ERROR(ARCHIVE, 0);
+		return (NULL);
+	}
+
+	/*
+	 * Adjust the size field for members in BSD archives using
+	 * extended naming.
+	 */
+	if (IS_EXTENDED_BSD_NAME(arh->ar_name)) {
+		namelen = arh->ar_name +
+		    LIBELF_AR_BSD_EXTENDED_NAME_PREFIX_SIZE;
+		if (_libelf_ar_get_number(namelen, sizeof(arh->ar_name) -
+		    LIBELF_AR_BSD_EXTENDED_NAME_PREFIX_SIZE, 10, &nsz) == 0) {
+			LIBELF_SET_ERROR(ARCHIVE, 0);
+			return (NULL);
+		}
+
+		member = (char *) (arh + 1) + nsz;
+		sz -= nsz;
+	} else
+		member = (char *) (arh + 1);
+
+
+	if ((e = elf_memory(member, sz)) == NULL)
+		return (NULL);
+
+	e->e_fd = fd;
+	e->e_cmd = c;
+	e->e_hdr.e_rawhdr = (unsigned char *) arh;
+
+	elf->e_u.e_ar.e_nchildren++;
+	e->e_parent = elf;
+
+	return (e);
+}
+
+/*
+ * A BSD-style ar(1) symbol table has the following layout:
+ *
+ * - A count of bytes used by the following array of 'ranlib'
+ *   structures, stored as a 'long'.
+ * - An array of 'ranlib' structures.  Each array element is
+ *   two 'long's in size.
+ * - A count of bytes used for the following symbol table.
+ * - The symbol table itself.
+ */
+
+/*
+ * A helper macro to read in a 'long' value from the archive.
+ *
+ * We use memcpy() since the source pointer may be misaligned with
+ * respect to the natural alignment for a C 'long'.
+ */
+#define	GET_LONG(P, V)do {				\
+		memcpy(&(V), (P), sizeof(long));	\
+		(P) += sizeof(long);			\
+	} while (0)
+
+Elf_Arsym *
+_libelf_ar_process_bsd_symtab(Elf *e, size_t *count)
+{
+	Elf_Arsym *symtab, *sym;
+	unsigned int n, nentries;
+	unsigned char *end, *p, *p0, *s, *s0;
+	const size_t entrysize = 2 * sizeof(long);
+	long arraysize, fileoffset, stroffset, strtabsize;
+
+	assert(e != NULL);
+	assert(count != NULL);
+	assert(e->e_u.e_ar.e_symtab == NULL);
+
+	symtab = NULL;
+
+	/*
+	 * The BSD symbol table always contains the count fields even
+	 * if there are no entries in it.
+	 */
+	if (e->e_u.e_ar.e_rawsymtabsz < 2 * sizeof(long))
+		goto symtaberror;
+
+	p = p0 = (unsigned char *) e->e_u.e_ar.e_rawsymtab;
+	end = p0 + e->e_u.e_ar.e_rawsymtabsz;
+
+	/*
+	 * Retrieve the size of the array of ranlib descriptors and
+	 * check it for validity.
+	 */
+	GET_LONG(p, arraysize);
+
+	if (arraysize < 0 || p0 + arraysize >= end ||
+	    ((size_t) arraysize % entrysize != 0))
+		goto symtaberror;
+
+	/*
+	 * Check the value of the string table size.
+	 */
+	s = p + arraysize;
+	GET_LONG(s, strtabsize);
+
+	s0 = s;			/* Start of string table. */
+	if (strtabsize < 0 || s0 + strtabsize > end)
+		goto symtaberror;
+
+	nentries = (size_t) arraysize / entrysize;
+
+	/*
+	 * Allocate space for the returned Elf_Arsym array.
+	 */
+	if ((symtab = malloc(sizeof(Elf_Arsym) * (nentries + 1))) == NULL) {
+		LIBELF_SET_ERROR(RESOURCE, 0);
+		return (NULL);
+	}
+
+	/* Read in symbol table entries. */
+	for (n = 0, sym = symtab; n < nentries; n++, sym++) {
+		GET_LONG(p, stroffset);
+		GET_LONG(p, fileoffset);
+
+		if (stroffset < 0 || fileoffset <  0 ||
+		    (size_t) fileoffset >= e->e_rawsize)
+			goto symtaberror;
+
+		s = s0 + stroffset;
+
+		if (s >= end)
+			goto symtaberror;
+
+		sym->as_off = (off_t) fileoffset;
+		sym->as_hash = elf_hash((char *) s);
+		sym->as_name = (char *) s;
+	}
+
+	/* Fill up the sentinel entry. */
+	sym->as_name = NULL;
+	sym->as_hash = ~0UL;
+	sym->as_off = (off_t) 0;
+
+	/* Remember the processed symbol table. */
+	e->e_u.e_ar.e_symtab = symtab;
+
+	*count = e->e_u.e_ar.e_symtabsz = nentries + 1;
+
+	return (symtab);
+
+symtaberror:
+	if (symtab)
+		free(symtab);
+	LIBELF_SET_ERROR(ARCHIVE, 0);
+	return (NULL);
+}
+
+/*
+ * An SVR4-style ar(1) symbol table has the following layout:
+ *
+ * - The first 4 bytes are a binary count of the number of entries in the
+ *   symbol table, stored MSB-first.
+ * - Then there are 'n' 4-byte binary offsets, also stored MSB first.
+ * - Following this, there are 'n' null-terminated strings.
+ */
+
+#define	GET_WORD(P, V) do {			\
+		(V) = 0;			\
+		(V) = (P)[0]; (V) <<= 8;	\
+		(V) += (P)[1]; (V) <<= 8;	\
+		(V) += (P)[2]; (V) <<= 8;	\
+		(V) += (P)[3];			\
+	} while (0)
+
+#define	INTSZ	4
+
+
+Elf_Arsym *
+_libelf_ar_process_svr4_symtab(Elf *e, size_t *count)
+{
+	uint32_t off;
+	size_t n, nentries;
+	Elf_Arsym *symtab, *sym;
+	unsigned char *p, *s, *end;
+
+	assert(e != NULL);
+	assert(count != NULL);
+	assert(e->e_u.e_ar.e_symtab == NULL);
+
+	symtab = NULL;
+
+	if (e->e_u.e_ar.e_rawsymtabsz < INTSZ)
+		goto symtaberror;
+
+	p = (unsigned char *) e->e_u.e_ar.e_rawsymtab;
+	end = p + e->e_u.e_ar.e_rawsymtabsz;
+
+	GET_WORD(p, nentries);
+	p += INTSZ;
+
+	if (nentries == 0 || p + nentries * INTSZ >= end)
+		goto symtaberror;
+
+	/* Allocate space for a nentries + a sentinel. */
+	if ((symtab = malloc(sizeof(Elf_Arsym) * (nentries+1))) == NULL) {
+		LIBELF_SET_ERROR(RESOURCE, 0);
+		return (NULL);
+	}
+
+	s = p + (nentries * INTSZ); /* start of the string table. */
+
+	for (n = nentries, sym = symtab; n > 0; n--) {
+		if (s >= end)
+			goto symtaberror;
+
+		GET_WORD(p, off);
+		if (off >= e->e_rawsize)
+			goto symtaberror;
+
+		sym->as_off = (off_t) off;
+		sym->as_hash = elf_hash((char *) s);
+		sym->as_name = (char *) s;
+
+		p += INTSZ;
+		sym++;
+
+		for (; s < end && *s++ != '\0';) /* skip to next string */
+			;
+	}
+
+	/* Fill up the sentinel entry. */
+	sym->as_name = NULL;
+	sym->as_hash = ~0UL;
+	sym->as_off = (off_t) 0;
+
+	*count = e->e_u.e_ar.e_symtabsz = nentries + 1;
+	e->e_u.e_ar.e_symtab = symtab;
+
+	return (symtab);
+
+symtaberror:
+	if (symtab)
+		free(symtab);
+	LIBELF_SET_ERROR(ARCHIVE, 0);
+	return (NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/libelf_ar_util.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,360 @@
+/*-
+ * Copyright (c) 2006,2009,2010 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS `AS IS' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <libelf.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "_libelf.h"
+#include "_libelf_ar.h"
+
+ELFTC_VCSID("$Id: libelf_ar_util.c 3174 2015-03-27 17:13:41Z emaste $");
+
+/*
+ * Convert a string bounded by `start' and `start+sz' (exclusive) to a
+ * number in the specified base.
+ */
+int
+_libelf_ar_get_number(const char *src, size_t sz, unsigned int base,
+    size_t *ret)
+{
+	size_t r;
+	unsigned int c, v;
+	const unsigned char *e, *s;
+
+	assert(base <= 10);
+
+	s = (const unsigned char *) src;
+	e = s + sz;
+
+	/* skip leading blanks */
+	for (;s < e && (c = *s) == ' '; s++)
+		;
+
+	r = 0L;
+	for (;s < e; s++) {
+		if ((c = *s) == ' ')
+			break;
+		if (c < '0' || c > '9')
+			return (0);
+		v = c - '0';
+		if (v >= base)		/* Illegal digit. */
+			break;
+		r *= base;
+		r += v;
+	}
+
+	*ret = r;
+
+	return (1);
+}
+
+/*
+ * Return the translated name for an archive member.
+ */
+char *
+_libelf_ar_get_translated_name(const struct ar_hdr *arh, Elf *ar)
+{
+	char *s;
+	unsigned char c;
+	size_t len, offset;
+	const unsigned char *buf, *p, *q, *r;
+	const size_t bufsize = sizeof(arh->ar_name);
+
+	assert(arh != NULL);
+	assert(ar->e_kind == ELF_K_AR);
+	assert((const unsigned char *) arh >= ar->e_rawfile &&
+	    (const unsigned char *) arh < ar->e_rawfile + ar->e_rawsize);
+
+	buf = (const unsigned char *) arh->ar_name;
+
+	/*
+	 * Check for extended naming.
+	 *
+	 * If the name matches the pattern "^/[0-9]+", it is an
+	 * SVR4-style extended name.  If the name matches the pattern
+	 * "#1/[0-9]+", the entry uses BSD style extended naming.
+	 */
+	if (buf[0] == '/' && (c = buf[1]) >= '0' && c <= '9') {
+		/*
+		 * The value in field ar_name is a decimal offset into
+		 * the archive string table where the actual name
+		 * resides.
+		 */
+		if (_libelf_ar_get_number((const char *) (buf + 1),
+			bufsize - 1, 10, &offset) == 0) {
+			LIBELF_SET_ERROR(ARCHIVE, 0);
+			return (NULL);
+		}
+
+		if (offset > ar->e_u.e_ar.e_rawstrtabsz) {
+			LIBELF_SET_ERROR(ARCHIVE, 0);
+			return (NULL);
+		}
+
+		p = q = ar->e_u.e_ar.e_rawstrtab + offset;
+		r = ar->e_u.e_ar.e_rawstrtab + ar->e_u.e_ar.e_rawstrtabsz;
+
+		for (; p < r && *p != '/'; p++)
+			;
+		len = (size_t) (p - q + 1); /* space for the trailing NUL */
+
+		if ((s = malloc(len)) == NULL) {
+			LIBELF_SET_ERROR(RESOURCE, 0);
+			return (NULL);
+		}
+
+		(void) strncpy(s, (const char *) q, len - 1);
+		s[len - 1] = '\0';
+
+		return (s);
+	} else if (IS_EXTENDED_BSD_NAME(buf)) {
+		r = buf + LIBELF_AR_BSD_EXTENDED_NAME_PREFIX_SIZE;
+
+		if (_libelf_ar_get_number((const char *) r, bufsize -
+			LIBELF_AR_BSD_EXTENDED_NAME_PREFIX_SIZE, 10,
+			&len) == 0) {
+			LIBELF_SET_ERROR(ARCHIVE, 0);
+			return (NULL);
+		}
+
+		/*
+		 * Allocate space for the file name plus a
+		 * trailing NUL.
+		 */
+		if ((s = malloc(len + 1)) == NULL) {
+			LIBELF_SET_ERROR(RESOURCE, 0);
+			return (NULL);
+		}
+
+		/*
+		 * The file name follows the archive header.
+		 */
+		q = (const unsigned char *) (arh + 1);
+
+		(void) strncpy(s, (const char *) q, len);
+		s[len] = '\0';
+
+		return (s);
+	}
+
+	/*
+	 * A 'normal' name.
+	 *
+	 * Skip back over trailing blanks from the end of the field.
+	 * In the SVR4 format, a '/' is used as a terminator for
+	 * non-special names.
+	 */
+	for (q = buf + bufsize - 1; q >= buf && *q == ' '; --q)
+		;
+
+	if (q >= buf) {
+		if (*q == '/') {
+			/*
+			 * SVR4 style names: ignore the trailing
+			 * character '/', but only if the name is not
+			 * one of the special names "/" and "//".
+			 */
+			if (q > buf + 1 ||
+			    (q == (buf + 1) && *buf != '/'))
+				q--;
+		}
+
+		len = (size_t) (q - buf + 2); /* Space for a trailing NUL. */
+	} else {
+		/* The buffer only had blanks. */
+		buf = (const unsigned char *) "";
+		len = 1;
+	}
+
+	if ((s = malloc(len)) == NULL) {
+		LIBELF_SET_ERROR(RESOURCE, 0);
+		return (NULL);
+	}
+
+	(void) strncpy(s, (const char *) buf, len - 1);
+	s[len - 1] = '\0';
+
+	return (s);
+}
+
+/*
+ * Return the raw name for an archive member, inclusive of any
+ * formatting characters.
+ */
+char *
+_libelf_ar_get_raw_name(const struct ar_hdr *arh)
+{
+	char *rawname;
+	const size_t namesz = sizeof(arh->ar_name);
+
+	if ((rawname = malloc(namesz + 1)) == NULL) {
+		LIBELF_SET_ERROR(RESOURCE, 0);
+		return (NULL);
+	}
+
+	(void) strncpy(rawname, arh->ar_name, namesz);
+	rawname[namesz] = '\0';
+	return (rawname);
+}
+
+/*
+ * Open an 'ar' archive.
+ */
+Elf *
+_libelf_ar_open(Elf *e, int reporterror)
+{
+	size_t sz;
+	int scanahead;
+	struct ar_hdr arh;
+	unsigned char *s, *end;
+
+	_libelf_init_elf(e, ELF_K_AR);
+
+	e->e_u.e_ar.e_nchildren = 0;
+	e->e_u.e_ar.e_next = (off_t) -1;
+
+	/*
+	 * Look for special members.
+	 */
+
+	s = e->e_rawfile + SARMAG;
+	end = e->e_rawfile + e->e_rawsize;
+
+	assert(e->e_rawsize > 0);
+
+	/*
+	 * We use heuristics to determine the flavor of the archive we
+	 * are examining.
+	 *
+	 * SVR4 flavor archives use the name "/ " and "// " for
+	 * special members.
+	 *
+	 * In BSD flavor archives the symbol table, if present, is the
+	 * first archive with name "__.SYMDEF".
+	 */
+
+#define	READ_AR_HEADER(S, ARH, SZ, END)					\
+	do {								\
+		if ((S) + sizeof((ARH)) > (END))			\
+		        goto error;					\
+		(void) memcpy(&(ARH), (S), sizeof((ARH)));		\
+		if ((ARH).ar_fmag[0] != '`' || (ARH).ar_fmag[1] != '\n') \
+			goto error;					\
+		if (_libelf_ar_get_number((char *) (ARH).ar_size,	\
+		    sizeof((ARH).ar_size), 10, &(SZ)) == 0)		\
+			goto error;					\
+	} while (0)
+
+	READ_AR_HEADER(s, arh, sz, end);
+
+	/*
+	 * Handle special archive members for the SVR4 format.
+	 */
+	if (arh.ar_name[0] == '/') {
+		if (sz == 0)
+			goto error;
+
+		e->e_flags |= LIBELF_F_AR_VARIANT_SVR4;
+
+		scanahead = 0;
+
+		/*
+		 * The symbol table (file name "/ ") always comes before the
+		 * string table (file name "// ").
+		 */
+		if (arh.ar_name[1] == ' ') {
+			/* "/ " => symbol table. */
+			scanahead = 1;	/* The string table to follow. */
+
+			s += sizeof(arh);
+			e->e_u.e_ar.e_rawsymtab = s;
+			e->e_u.e_ar.e_rawsymtabsz = sz;
+
+			sz = LIBELF_ADJUST_AR_SIZE(sz);
+			s += sz;
+
+		} else if (arh.ar_name[1] == '/' && arh.ar_name[2] == ' ') {
+			/* "// " => string table for long file names. */
+			s += sizeof(arh);
+			e->e_u.e_ar.e_rawstrtab = s;
+			e->e_u.e_ar.e_rawstrtabsz = sz;
+
+			sz = LIBELF_ADJUST_AR_SIZE(sz);
+			s += sz;
+		}
+
+		/*
+		 * If the string table hasn't been seen yet, look for
+		 * it in the next member.
+		 */
+		if (scanahead) {
+			READ_AR_HEADER(s, arh, sz, end);
+
+			/* "// " => string table for long file names. */
+			if (arh.ar_name[0] == '/' && arh.ar_name[1] == '/' &&
+			    arh.ar_name[2] == ' ') {
+
+				s += sizeof(arh);
+
+				e->e_u.e_ar.e_rawstrtab = s;
+				e->e_u.e_ar.e_rawstrtabsz = sz;
+
+				sz = LIBELF_ADJUST_AR_SIZE(sz);
+				s += sz;
+			}
+		}
+	} else if (strncmp(arh.ar_name, LIBELF_AR_BSD_SYMTAB_NAME,
+		sizeof(LIBELF_AR_BSD_SYMTAB_NAME) - 1) == 0) {
+		/*
+		 * BSD style archive symbol table.
+		 */
+		s += sizeof(arh);
+		e->e_u.e_ar.e_rawsymtab = s;
+		e->e_u.e_ar.e_rawsymtabsz = sz;
+
+		sz = LIBELF_ADJUST_AR_SIZE(sz);
+		s += sz;
+	}
+
+	/*
+	 * Update the 'next' offset, so that a subsequent elf_begin()
+	 * works as expected.
+	 */
+	e->e_u.e_ar.e_next = (off_t) (s - e->e_rawfile);
+
+	return (e);
+
+error:
+	if (!reporterror) {
+		e->e_kind = ELF_K_NONE;
+		return (e);
+	}
+
+	LIBELF_SET_ERROR(ARCHIVE, 0);
+	return (NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/libelf_checksum.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,98 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <gelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: libelf_checksum.c 3174 2015-03-27 17:13:41Z emaste $");
+
+static unsigned long
+_libelf_sum(unsigned long c, const unsigned char *s, size_t size)
+{
+	if (s == NULL || size == 0)
+		return (c);
+
+	while (size--)
+		c += *s++;
+
+	return (c);
+}
+
+long
+_libelf_checksum(Elf *e, int elfclass)
+{
+	size_t shn;
+	Elf_Scn *scn;
+	Elf_Data *d;
+	unsigned long checksum;
+	GElf_Ehdr eh;
+	GElf_Shdr shdr;
+
+	if (e == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (0L);
+	}
+
+	if (e->e_class != elfclass) {
+		LIBELF_SET_ERROR(CLASS, 0);
+		return (0L);
+	}
+
+	if (gelf_getehdr(e, &eh) == NULL)
+		return (0);
+
+	/*
+	 * Iterate over all sections in the ELF file, computing the
+	 * checksum along the way.
+	 *
+	 * The first section is always SHN_UNDEF and can be skipped.
+	 * Non-allocatable sections are skipped, as are sections that
+	 * could be affected by utilities such as strip(1).
+	 */
+
+	checksum = 0;
+	for (shn = 1; shn < e->e_u.e_elf.e_nscn; shn++) {
+		if ((scn = elf_getscn(e, shn)) == NULL)
+			return (0);
+		if (gelf_getshdr(scn, &shdr) == NULL)
+			return (0);
+		if ((shdr.sh_flags & SHF_ALLOC) == 0 ||
+		    shdr.sh_type == SHT_DYNAMIC ||
+		    shdr.sh_type == SHT_DYNSYM)
+			continue;
+
+		d = NULL;
+		while ((d = elf_rawdata(scn, d)) != NULL)
+			checksum = _libelf_sum(checksum,
+			    (unsigned char *) d->d_buf, (size_t) d->d_size);
+	}
+
+	/*
+	 * Return a 16-bit checksum compatible with Solaris.
+	 */
+	return (long) (((checksum >> 16) & 0xFFFFUL) + (checksum & 0xFFFFUL));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/libelf_convert.m4	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,1088 @@
+/*-
+ * Copyright (c) 2006-2011 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <libelf.h>
+#include <string.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: libelf_convert.m4 3429 2016-03-12 04:12:39Z emaste $");
+
+/* WARNING: GENERATED FROM __file__. */
+
+divert(-1)
+
+# Generate conversion routines for converting between in-memory and
+# file representations of Elf data structures.
+#
+# These conversions use the type information defined in `elf_types.m4'.
+
+include(SRCDIR`/elf_types.m4')
+
+# For the purposes of generating conversion code, ELF types may be
+# classified according to the following characteristics:
+#
+# 1. Whether the ELF type can be directly mapped to an integral C
+#    language type.  For example, the ELF_T_WORD type maps directly to
+#    a 'uint32_t', but ELF_T_GNUHASH lacks a matching C type.
+#
+# 2. Whether the type has word size dependent variants.  For example,
+#    ELT_T_EHDR is represented using C types Elf32_Ehdr and El64_Ehdr,
+#    and the ELF_T_ADDR and ELF_T_OFF types have integral C types that
+#    can be 32- or 64- bit wide.
+#
+# 3. Whether the ELF types has a fixed representation or not.  For
+#    example, the ELF_T_SYM type has a fixed size file representation,
+#    some types like ELF_T_NOTE and ELF_T_GNUHASH use a variable size
+#    representation.
+#
+# We use m4 macros to generate conversion code for ELF types that have
+# a fixed size representation.  Conversion functions for the remaining
+# types are coded by hand.
+#
+#* Handling File and Memory Representations
+#
+# `In-memory' representations of an Elf data structure use natural
+# alignments and native byte ordering.  This allows pointer arithmetic
+# and casting to work as expected.  On the other hand, the `file'
+# representation of an ELF data structure could possibly be packed
+# tighter than its `in-memory' representation, and could be of a
+# differing byte order.  Reading ELF objects that are members of `ar'
+# archives present an additional complication: `ar' pads file data to
+# even addresses, so file data structures in an archive member
+# residing inside an `ar' archive could be at misaligned memory
+# addresses when brought into memory.
+#
+# In summary, casting the `char *' pointers that point to memory
+# representations (i.e., source pointers for the *_tof() functions and
+# the destination pointers for the *_tom() functions), is safe, as
+# these pointers should be correctly aligned for the memory type
+# already.  However, pointers to file representations have to be
+# treated as being potentially unaligned and no casting can be done.
+
+# NOCVT(TYPE) -- Do not generate the cvt[] structure entry for TYPE
+define(`NOCVT',`define(`NOCVT_'$1,1)')
+
+# NOFUNC(TYPE) -- Do not generate a conversion function for TYPE
+define(`NOFUNC',`define(`NOFUNC_'$1,1)')
+
+# IGNORE(TYPE) -- Completely ignore the type.
+define(`IGNORE',`NOCVT($1)NOFUNC($1)')
+
+# Mark ELF types that should not be processed by the M4 macros below.
+
+# Types for which we use functions with non-standard names.
+IGNORE(`BYTE')			# Uses a wrapper around memcpy().
+IGNORE(`NOTE')			# Not a fixed size type.
+
+# Types for which we supply hand-coded functions.
+NOFUNC(`GNUHASH')		# A type with complex internal structure.
+NOFUNC(`VDEF')			# See MAKE_VERSION_CONVERTERS below.
+NOFUNC(`VNEED')			# ..
+
+# Unimplemented types.
+IGNORE(`MOVEP')
+
+# ELF types that don't exist in a 32-bit world.
+NOFUNC(`XWORD32')
+NOFUNC(`SXWORD32')
+
+# `Primitive' ELF types are those that are an alias for an integral
+# type.  As they have no internal structure, they can be copied using
+# a `memcpy()', and byteswapped in straightforward way.
+#
+# Mark all ELF types that directly map to integral C types.
+define(`PRIM_ADDR',	1)
+define(`PRIM_BYTE',	1)
+define(`PRIM_HALF',	1)
+define(`PRIM_LWORD',	1)
+define(`PRIM_OFF',	1)
+define(`PRIM_SWORD',	1)
+define(`PRIM_SXWORD',	1)
+define(`PRIM_WORD',	1)
+define(`PRIM_XWORD',	1)
+
+# Note the primitive types that are size-dependent.
+define(`SIZEDEP_ADDR',	1)
+define(`SIZEDEP_OFF',	1)
+
+# Generate conversion functions for primitive types.
+#
+# Macro use: MAKEPRIMFUNCS(ELFTYPE,CTYPE,TYPESIZE,SYMSIZE)
+# `$1': Name of the ELF type.
+# `$2': C structure name suffix.
+# `$3': ELF class specifier for types, one of [`32', `64'].
+# `$4': Additional ELF class specifier, one of [`', `32', `64'].
+#
+# Generates a pair of conversion functions.
+define(`MAKEPRIMFUNCS',`
+static int
+_libelf_cvt_$1$4_tof(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+	Elf$3_$2 t, *s = (Elf$3_$2 *) (uintptr_t) src;
+	size_t c;
+
+	(void) dsz;
+
+	if (!byteswap) {
+		(void) memcpy(dst, src, count * sizeof(*s));
+		return (1);
+	}
+
+	for (c = 0; c < count; c++) {
+		t = *s++;
+		SWAP_$1$4(t);
+		WRITE_$1$4(dst,t);
+	}
+
+	return (1);
+}
+
+static int
+_libelf_cvt_$1$4_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+	Elf$3_$2 t, *d = (Elf$3_$2 *) (uintptr_t) dst;
+	size_t c;
+
+	if (dsz < count * sizeof(Elf$3_$2))
+		return (0);
+
+	if (!byteswap) {
+		(void) memcpy(dst, src, count * sizeof(*d));
+		return (1);
+	}
+
+	for (c = 0; c < count; c++) {
+		READ_$1$4(src,t);
+		SWAP_$1$4(t);
+		*d++ = t;
+	}
+
+	return (1);
+}
+')
+
+#
+# Handling composite ELF types
+#
+
+# SWAP_FIELD(FIELDNAME,ELFTYPE) -- Generate code to swap one field.
+define(`SWAP_FIELD',
+  `ifdef(`SIZEDEP_'$2,
+    `SWAP_$2'SZ()`(t.$1);
+			',
+    `SWAP_$2(t.$1);
+			')')
+
+# SWAP_MEMBERS(STRUCT) -- Iterate over a structure definition.
+define(`SWAP_MEMBERS',
+  `ifelse($#,1,`/**/',
+     `SWAP_FIELD($1)SWAP_MEMBERS(shift($@))')')
+
+# SWAP_STRUCT(CTYPE,SIZE) -- Generate code to swap an ELF structure.
+define(`SWAP_STRUCT',
+  `pushdef(`SZ',$2)/* Swap an Elf$2_$1 */
+			SWAP_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
+
+# WRITE_FIELD(ELFTYPE,FIELDNAME) -- Generate code to write one field.
+define(`WRITE_FIELD',
+  `ifdef(`SIZEDEP_'$2,
+    `WRITE_$2'SZ()`(dst,t.$1);
+		',
+    `WRITE_$2(dst,t.$1);
+		')')
+
+# WRITE_MEMBERS(ELFTYPELIST) -- Iterate over a structure definition.
+define(`WRITE_MEMBERS',
+  `ifelse($#,1,`/**/',
+    `WRITE_FIELD($1)WRITE_MEMBERS(shift($@))')')
+
+# WRITE_STRUCT(CTYPE,SIZE) -- Generate code to write out an ELF structure.
+define(`WRITE_STRUCT',
+  `pushdef(`SZ',$2)/* Write an Elf$2_$1 */
+		WRITE_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
+
+# READ_FIELD(ELFTYPE,CTYPE) -- Generate code to read one field.
+define(`READ_FIELD',
+  `ifdef(`SIZEDEP_'$2,
+    `READ_$2'SZ()`(s,t.$1);
+		',
+    `READ_$2(s,t.$1);
+		')')
+
+# READ_MEMBERS(ELFTYPELIST) -- Iterate over a structure definition.
+define(`READ_MEMBERS',
+  `ifelse($#,1,`/**/',
+    `READ_FIELD($1)READ_MEMBERS(shift($@))')')
+
+# READ_STRUCT(CTYPE,SIZE) -- Generate code to read an ELF structure.
+define(`READ_STRUCT',
+  `pushdef(`SZ',$2)/* Read an Elf$2_$1 */
+		READ_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
+
+
+# MAKECOMPFUNCS -- Generate converters for composite ELF structures.
+#
+# When converting data to file representation, the source pointer will
+# be naturally aligned for a data structure's in-memory
+# representation.  When converting data to memory, the destination
+# pointer will be similarly aligned.
+#
+# For in-place conversions, when converting to file representations,
+# the source buffer is large enough to hold `file' data.  When
+# converting from file to memory, we need to be careful to work
+# `backwards', to avoid overwriting unconverted data.
+#
+# Macro use:
+# `$1': Name of the ELF type.
+# `$2': C structure name suffix.
+# `$3': ELF class specifier, one of [`', `32', `64']
+define(`MAKECOMPFUNCS', `ifdef(`NOFUNC_'$1$3,`',`
+static int
+_libelf_cvt_$1$3_tof(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+	Elf$3_$2	t, *s;
+	size_t c;
+
+	(void) dsz;
+
+	s = (Elf$3_$2 *) (uintptr_t) src;
+	for (c = 0; c < count; c++) {
+		t = *s++;
+		if (byteswap) {
+			SWAP_STRUCT($2,$3)
+		}
+		WRITE_STRUCT($2,$3)
+	}
+
+	return (1);
+}
+
+static int
+_libelf_cvt_$1$3_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+	Elf$3_$2	t, *d;
+	unsigned char	*s,*s0;
+	size_t		fsz;
+
+	fsz = elf$3_fsize(ELF_T_$1, (size_t) 1, EV_CURRENT);
+	d   = ((Elf$3_$2 *) (uintptr_t) dst) + (count - 1);
+	s0  = src + (count - 1) * fsz;
+
+	if (dsz < count * sizeof(Elf$3_$2))
+		return (0);
+
+	while (count--) {
+		s = s0;
+		READ_STRUCT($2,$3)
+		if (byteswap) {
+			SWAP_STRUCT($2,$3)
+		}
+		*d-- = t; s0 -= fsz;
+	}
+
+	return (1);
+}
+')')
+
+# MAKE_TYPE_CONVERTER(ELFTYPE,CTYPE)
+#
+# Make type convertor functions from the type definition
+# of the ELF type:
+# - Skip convertors marked as `NOFUNC'.
+# - Invoke `MAKEPRIMFUNCS' or `MAKECOMPFUNCS' as appropriate.
+define(`MAKE_TYPE_CONVERTER',
+  `ifdef(`NOFUNC_'$1,`',
+    `ifdef(`PRIM_'$1,
+      `ifdef(`SIZEDEP_'$1,
+	`MAKEPRIMFUNCS($1,$2,32,32)dnl
+	 MAKEPRIMFUNCS($1,$2,64,64)',
+	`MAKEPRIMFUNCS($1,$2,64)')',
+      `MAKECOMPFUNCS($1,$2,32)dnl
+       MAKECOMPFUNCS($1,$2,64)')')')
+
+# MAKE_TYPE_CONVERTERS(ELFTYPELIST) -- Generate conversion functions.
+define(`MAKE_TYPE_CONVERTERS',
+  `ifelse($#,1,`',
+    `MAKE_TYPE_CONVERTER($1)MAKE_TYPE_CONVERTERS(shift($@))')')
+
+
+#
+# Macros to generate entries for the table of convertors.
+#
+
+# CONV(ELFTYPE,SIZE,DIRECTION)
+#
+# Generate the name of a convertor function.
+define(`CONV',
+  `ifdef(`NOFUNC_'$1$2,
+    `.$3$2 = NULL',
+    `ifdef(`PRIM_'$1,
+      `ifdef(`SIZEDEP_'$1,
+	`.$3$2 = _libelf_cvt_$1$2_$3',
+	`.$3$2 = _libelf_cvt_$1_$3')',
+      `.$3$2 = _libelf_cvt_$1$2_$3')')')
+
+# CONVERTER_NAME(ELFTYPE)
+#
+# Generate the contents of one `struct cvt' instance.
+define(`CONVERTER_NAME',
+  `ifdef(`NOCVT_'$1,`',
+    `	[ELF_T_$1] = {
+		CONV($1,32,tof),
+		CONV($1,32,tom),
+		CONV($1,64,tof),
+		CONV($1,64,tom)
+	},
+
+')')
+
+# CONVERTER_NAMES(ELFTYPELIST)
+#
+# Generate the `struct cvt[]' array.
+define(`CONVERTER_NAMES',
+  `ifelse($#,1,`',
+    `CONVERTER_NAME($1)CONVERTER_NAMES(shift($@))')')
+
+#
+# Handling ELF version sections.
+#
+
+# _FSZ(FIELD,BASETYPE) - return the file size for a field.
+define(`_FSZ',
+  `ifelse($2,`HALF',2,
+     $2,`WORD',4)')
+
+# FSZ(STRUCT) - determine the file size of a structure.
+define(`FSZ',
+  `ifelse($#,1,0,
+    `eval(_FSZ($1) + FSZ(shift($@)))')')
+
+# MAKE_VERSION_CONVERTERS(TYPE,BASE,AUX,PFX) -- Generate conversion
+# functions for versioning structures.
+define(`MAKE_VERSION_CONVERTERS',
+  `MAKE_VERSION_CONVERTER($1,$2,$3,$4,32)
+   MAKE_VERSION_CONVERTER($1,$2,$3,$4,64)')
+
+# MAKE_VERSION_CONVERTOR(TYPE,CBASE,CAUX,PFX,SIZE) -- Generate a
+# conversion function.
+define(`MAKE_VERSION_CONVERTER',`
+static int
+_libelf_cvt_$1$5_tof(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+	Elf$5_$2	t;
+	Elf$5_$3	a;
+	const size_t	verfsz = FSZ(Elf$5_$2_DEF);
+	const size_t	auxfsz = FSZ(Elf$5_$3_DEF);
+	const size_t	vermsz = sizeof(Elf$5_$2);
+	const size_t	auxmsz = sizeof(Elf$5_$3);
+	unsigned char * const dstend = dst + dsz;
+	unsigned char * const srcend = src + count;
+	unsigned char	*dtmp, *dstaux, *srcaux;
+	Elf$5_Word	aux, anext, cnt, vnext;
+
+	for (dtmp = dst, vnext = ~0U;
+	     vnext != 0 && dtmp + verfsz <= dstend && src + vermsz <= srcend;
+	     dtmp += vnext, src += vnext) {
+
+		/* Read in an Elf$5_$2 structure. */
+		t = *((Elf$5_$2 *) (uintptr_t) src);
+
+		aux = t.$4_aux;
+		cnt = t.$4_cnt;
+		vnext = t.$4_next;
+
+		if (byteswap) {
+			SWAP_STRUCT($2, $5)
+		}
+
+		dst = dtmp;
+		WRITE_STRUCT($2, $5)
+
+		if (aux < verfsz)
+			return (0);
+
+		/* Process AUX entries. */
+		for (anext = ~0U, dstaux = dtmp + aux, srcaux = src + aux;
+		     cnt != 0 && anext != 0 && dstaux + auxfsz <= dstend &&
+			srcaux + auxmsz <= srcend;
+		     dstaux += anext, srcaux += anext, cnt--) {
+
+			/* Read in an Elf$5_$3 structure. */
+			a = *((Elf$5_$3 *) (uintptr_t) srcaux);
+			anext = a.$4a_next;
+
+			if (byteswap) {
+				pushdef(`t',`a')SWAP_STRUCT($3, $5)popdef(`t')
+			}
+
+			dst = dstaux;
+			pushdef(`t',`a')WRITE_STRUCT($3, $5)popdef(`t')
+		}
+
+		if (anext || cnt)
+			return (0);
+	}
+
+	if (vnext)
+		return (0);
+
+	return (1);
+}
+
+static int
+_libelf_cvt_$1$5_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+	Elf$5_$2	t, *dp;
+	Elf$5_$3	a, *ap;
+	const size_t	verfsz = FSZ(Elf$5_$2_DEF);
+	const size_t	auxfsz = FSZ(Elf$5_$3_DEF);
+	const size_t	vermsz = sizeof(Elf$5_$2);
+	const size_t	auxmsz = sizeof(Elf$5_$3);
+	unsigned char * const dstend = dst + dsz;
+	unsigned char * const srcend = src + count;
+	unsigned char	*dstaux, *s, *srcaux, *stmp;
+	Elf$5_Word	aux, anext, cnt, vnext;
+
+	for (stmp = src, vnext = ~0U;
+	     vnext != 0 && stmp + verfsz <= srcend && dst + vermsz <= dstend;
+	     stmp += vnext, dst += vnext) {
+
+		/* Read in a $1 structure. */
+		s = stmp;
+		READ_STRUCT($2, $5)
+		if (byteswap) {
+			SWAP_STRUCT($2, $5)
+		}
+
+		dp = (Elf$5_$2 *) (uintptr_t) dst;
+		*dp = t;
+
+		aux = t.$4_aux;
+		cnt = t.$4_cnt;
+		vnext = t.$4_next;
+
+		if (aux < vermsz)
+			return (0);
+
+		/* Process AUX entries. */
+		for (anext = ~0U, dstaux = dst + aux, srcaux = stmp + aux;
+		     cnt != 0 && anext != 0 && dstaux + auxmsz <= dstend &&
+			srcaux + auxfsz <= srcend;
+		     dstaux += anext, srcaux += anext, cnt--) {
+
+			s = srcaux;
+			pushdef(`t',`a')READ_STRUCT($3, $5)popdef(`t')
+
+			if (byteswap) {
+				pushdef(`t',`a')SWAP_STRUCT($3, $5)popdef(`t')
+			}
+
+			anext = a.$4a_next;
+
+			ap = ((Elf$5_$3 *) (uintptr_t) dstaux);
+			*ap = a;
+		}
+
+		if (anext || cnt)
+			return (0);
+	}
+
+	if (vnext)
+		return (0);
+
+	return (1);
+}')
+
+divert(0)
+
+/*
+ * C macros to byte swap integral quantities.
+ */
+
+#define	SWAP_BYTE(X)	do { (void) (X); } while (0)
+#define	SWAP_IDENT(X)	do { (void) (X); } while (0)
+#define	SWAP_HALF(X)	do {						\
+		uint16_t _x = (uint16_t) (X);				\
+		uint32_t _t = _x & 0xFFU;				\
+		_t <<= 8U; _x >>= 8U; _t |= _x & 0xFFU;			\
+		(X) = (uint16_t) _t;					\
+	} while (0)
+#define	_SWAP_WORD(X, T) do {						\
+		uint32_t _x = (uint32_t) (X);				\
+		uint32_t _t = _x & 0xFF;				\
+		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
+		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
+		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
+		(X) = (T) _t;						\
+	} while (0)
+#define	SWAP_ADDR32(X)	_SWAP_WORD(X, Elf32_Addr)
+#define	SWAP_OFF32(X)	_SWAP_WORD(X, Elf32_Off)
+#define	SWAP_SWORD(X)	_SWAP_WORD(X, Elf32_Sword)
+#define	SWAP_WORD(X)	_SWAP_WORD(X, Elf32_Word)
+#define	_SWAP_WORD64(X, T) do {						\
+		uint64_t _x = (uint64_t) (X);				\
+		uint64_t _t = _x & 0xFF;				\
+		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
+		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
+		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
+		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
+		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
+		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
+		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
+		(X) = (T) _t;						\
+	} while (0)
+#define	SWAP_ADDR64(X)	_SWAP_WORD64(X, Elf64_Addr)
+#define	SWAP_LWORD(X)	_SWAP_WORD64(X, Elf64_Lword)
+#define	SWAP_OFF64(X)	_SWAP_WORD64(X, Elf64_Off)
+#define	SWAP_SXWORD(X)	_SWAP_WORD64(X, Elf64_Sxword)
+#define	SWAP_XWORD(X)	_SWAP_WORD64(X, Elf64_Xword)
+
+/*
+ * C macros to write out various integral values.
+ *
+ * Note:
+ * - The destination pointer could be unaligned.
+ * - Values are written out in native byte order.
+ * - The destination pointer is incremented after the write.
+ */
+#define	WRITE_BYTE(P,X) do {						\
+		unsigned char *const _p = (unsigned char *) (P);	\
+		_p[0]		= (unsigned char) (X);			\
+		(P)		= _p + 1;				\
+	} while (0)
+#define	WRITE_HALF(P,X)	do {						\
+		uint16_t _t	= (X);					\
+		unsigned char *const _p	= (unsigned char *) (P);	\
+		const unsigned char *const _q = (unsigned char *) &_t;	\
+		_p[0]		= _q[0];				\
+		_p[1]		= _q[1];				\
+		(P)		= _p + 2;				\
+	} while (0)
+#define	WRITE_WORD(P,X) do {						\
+		uint32_t _t	= (uint32_t) (X);			\
+		unsigned char *const _p	= (unsigned char *) (P);	\
+		const unsigned char *const _q = (unsigned char *) &_t;	\
+		_p[0]		= _q[0];				\
+		_p[1]		= _q[1];				\
+		_p[2]		= _q[2];				\
+		_p[3]		= _q[3];				\
+		(P)		= _p + 4;				\
+	} while (0)
+#define	WRITE_ADDR32(P,X)	WRITE_WORD(P,X)
+#define	WRITE_OFF32(P,X)	WRITE_WORD(P,X)
+#define	WRITE_SWORD(P,X)	WRITE_WORD(P,X)
+#define	WRITE_WORD64(P,X)	do {					\
+		uint64_t _t	= (uint64_t) (X);			\
+		unsigned char *const _p	= (unsigned char *) (P);	\
+		const unsigned char *const _q = (unsigned char *) &_t;	\
+		_p[0]		= _q[0];				\
+		_p[1]		= _q[1];				\
+		_p[2]		= _q[2];				\
+		_p[3]		= _q[3];				\
+		_p[4]		= _q[4];				\
+		_p[5]		= _q[5];				\
+		_p[6]		= _q[6];				\
+		_p[7]		= _q[7];				\
+		(P)		= _p + 8;				\
+	} while (0)
+#define	WRITE_ADDR64(P,X)	WRITE_WORD64(P,X)
+#define	WRITE_LWORD(P,X)	WRITE_WORD64(P,X)
+#define	WRITE_OFF64(P,X)	WRITE_WORD64(P,X)
+#define	WRITE_SXWORD(P,X)	WRITE_WORD64(P,X)
+#define	WRITE_XWORD(P,X)	WRITE_WORD64(P,X)
+#define	WRITE_IDENT(P,X)	do {					\
+		(void) memcpy((P), (X), sizeof((X)));			\
+		(P)		= (P) + EI_NIDENT;			\
+	} while (0)
+
+/*
+ * C macros to read in various integral values.
+ *
+ * Note:
+ * - The source pointer could be unaligned.
+ * - Values are read in native byte order.
+ * - The source pointer is incremented appropriately.
+ */
+
+#define	READ_BYTE(P,X)	do {						\
+		const unsigned char *const _p =				\
+			(const unsigned char *) (P);			\
+		(X)		= _p[0];				\
+		(P)		= (P) + 1;				\
+	} while (0)
+#define	READ_HALF(P,X)	do {						\
+		uint16_t _t;						\
+		unsigned char *const _q = (unsigned char *) &_t;	\
+		const unsigned char *const _p =				\
+			(const unsigned char *) (P);			\
+		_q[0]		= _p[0];				\
+		_q[1]		= _p[1];				\
+		(P)		= (P) + 2;				\
+		(X)		= _t;					\
+	} while (0)
+#define	_READ_WORD(P,X,T) do {						\
+		uint32_t _t;						\
+		unsigned char *const _q = (unsigned char *) &_t;	\
+		const unsigned char *const _p =				\
+			(const unsigned char *) (P);			\
+		_q[0]		= _p[0];				\
+		_q[1]		= _p[1];				\
+		_q[2]		= _p[2];				\
+		_q[3]		= _p[3];				\
+		(P)		= (P) + 4;				\
+		(X)		= (T) _t;				\
+	} while (0)
+#define	READ_ADDR32(P,X)	_READ_WORD(P, X, Elf32_Addr)
+#define	READ_OFF32(P,X)		_READ_WORD(P, X, Elf32_Off)
+#define	READ_SWORD(P,X)		_READ_WORD(P, X, Elf32_Sword)
+#define	READ_WORD(P,X)		_READ_WORD(P, X, Elf32_Word)
+#define	_READ_WORD64(P,X,T)	do {					\
+		uint64_t _t;						\
+		unsigned char *const _q = (unsigned char *) &_t;	\
+		const unsigned char *const _p =				\
+			(const unsigned char *) (P);			\
+		_q[0]		= _p[0];				\
+		_q[1]		= _p[1];				\
+		_q[2]		= _p[2];				\
+		_q[3]		= _p[3];				\
+		_q[4]		= _p[4];				\
+		_q[5]		= _p[5];				\
+		_q[6]		= _p[6];				\
+		_q[7]		= _p[7];				\
+		(P)		= (P) + 8;				\
+		(X)		= (T) _t;				\
+	} while (0)
+#define	READ_ADDR64(P,X)	_READ_WORD64(P, X, Elf64_Addr)
+#define	READ_LWORD(P,X)		_READ_WORD64(P, X, Elf64_Lword)
+#define	READ_OFF64(P,X)		_READ_WORD64(P, X, Elf64_Off)
+#define	READ_SXWORD(P,X)	_READ_WORD64(P, X, Elf64_Sxword)
+#define	READ_XWORD(P,X)		_READ_WORD64(P, X, Elf64_Xword)
+#define	READ_IDENT(P,X)		do {					\
+		(void) memcpy((X), (P), sizeof((X)));			\
+		(P)		= (P) + EI_NIDENT;			\
+	} while (0)
+
+#define	ROUNDUP2(V,N)	(V) = ((((V) + (N) - 1)) & ~((N) - 1))
+
+/*[*/
+MAKE_TYPE_CONVERTERS(ELF_TYPE_LIST)
+MAKE_VERSION_CONVERTERS(VDEF,Verdef,Verdaux,vd)
+MAKE_VERSION_CONVERTERS(VNEED,Verneed,Vernaux,vn)
+/*]*/
+
+/*
+ * Sections of type ELF_T_BYTE are never byteswapped, consequently a
+ * simple memcpy suffices for both directions of conversion.
+ */
+
+static int
+_libelf_cvt_BYTE_tox(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+	(void) byteswap;
+	if (dsz < count)
+		return (0);
+	if (dst != src)
+		(void) memcpy(dst, src, count);
+	return (1);
+}
+
+/*
+ * Sections of type ELF_T_GNUHASH start with a header containing 4 32-bit
+ * words.  Bloom filter data comes next, followed by hash buckets and the
+ * hash chain.
+ *
+ * Bloom filter words are 64 bit wide on ELFCLASS64 objects and are 32 bit
+ * wide on ELFCLASS32 objects.  The other objects in this section are 32
+ * bits wide.
+ *
+ * Argument `srcsz' denotes the number of bytes to be converted.  In the
+ * 32-bit case we need to translate `srcsz' to a count of 32-bit words.
+ */
+
+static int
+_libelf_cvt_GNUHASH32_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t srcsz, int byteswap)
+{
+	return (_libelf_cvt_WORD_tom(dst, dsz, src, srcsz / sizeof(uint32_t),
+		byteswap));
+}
+
+static int
+_libelf_cvt_GNUHASH32_tof(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t srcsz, int byteswap)
+{
+	return (_libelf_cvt_WORD_tof(dst, dsz, src, srcsz / sizeof(uint32_t),
+		byteswap));
+}
+
+static int
+_libelf_cvt_GNUHASH64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t srcsz, int byteswap)
+{
+	size_t sz;
+	uint64_t t64, *bloom64;
+	Elf_GNU_Hash_Header *gh;
+	uint32_t n, nbuckets, nchains, maskwords, shift2, symndx, t32;
+	uint32_t *buckets, *chains;
+
+	sz = 4 * sizeof(uint32_t);	/* File header is 4 words long. */
+	if (dsz < sizeof(Elf_GNU_Hash_Header) || srcsz < sz)
+		return (0);
+
+	/* Read in the section header and byteswap if needed. */
+	READ_WORD(src, nbuckets);
+	READ_WORD(src, symndx);
+	READ_WORD(src, maskwords);
+	READ_WORD(src, shift2);
+
+	srcsz -= sz;
+
+	if (byteswap) {
+		SWAP_WORD(nbuckets);
+		SWAP_WORD(symndx);
+		SWAP_WORD(maskwords);
+		SWAP_WORD(shift2);
+	}
+
+	/* Check source buffer and destination buffer sizes. */
+	sz = nbuckets * sizeof(uint32_t) + maskwords * sizeof(uint64_t);
+	if (srcsz < sz || dsz < sz + sizeof(Elf_GNU_Hash_Header))
+		return (0);
+
+	gh = (Elf_GNU_Hash_Header *) (uintptr_t) dst;
+	gh->gh_nbuckets  = nbuckets;
+	gh->gh_symndx    = symndx;
+	gh->gh_maskwords = maskwords;
+	gh->gh_shift2    = shift2;
+
+	dsz -= sizeof(Elf_GNU_Hash_Header);
+	dst += sizeof(Elf_GNU_Hash_Header);
+
+	bloom64 = (uint64_t *) (uintptr_t) dst;
+
+	/* Copy bloom filter data. */
+	for (n = 0; n < maskwords; n++) {
+		READ_XWORD(src, t64);
+		if (byteswap)
+			SWAP_XWORD(t64);
+		bloom64[n] = t64;
+	}
+
+	/* The hash buckets follows the bloom filter. */
+	dst += maskwords * sizeof(uint64_t);
+	buckets = (uint32_t *) (uintptr_t) dst;
+
+	for (n = 0; n < nbuckets; n++) {
+		READ_WORD(src, t32);
+		if (byteswap)
+			SWAP_WORD(t32);
+		buckets[n] = t32;
+	}
+
+	dst += nbuckets * sizeof(uint32_t);
+
+	/* The hash chain follows the hash buckets. */
+	dsz -= sz;
+	srcsz -= sz;
+
+	if (dsz < srcsz)	/* Destination lacks space. */
+		return (0);
+
+	nchains = srcsz / sizeof(uint32_t);
+	chains = (uint32_t *) (uintptr_t) dst;
+
+	for (n = 0; n < nchains; n++) {
+		READ_WORD(src, t32);
+		if (byteswap)
+			SWAP_WORD(t32);
+		*chains++ = t32;
+	}
+
+	return (1);
+}
+
+static int
+_libelf_cvt_GNUHASH64_tof(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t srcsz, int byteswap)
+{
+	uint32_t *s32;
+	size_t sz, hdrsz;
+	uint64_t *s64, t64;
+	Elf_GNU_Hash_Header *gh;
+	uint32_t maskwords, n, nbuckets, nchains, t0, t1, t2, t3, t32;
+
+	hdrsz = 4 * sizeof(uint32_t);	/* Header is 4x32 bits. */
+	if (dsz < hdrsz || srcsz < sizeof(Elf_GNU_Hash_Header))
+		return (0);
+
+	gh = (Elf_GNU_Hash_Header *) (uintptr_t) src;
+
+	t0 = nbuckets = gh->gh_nbuckets;
+	t1 = gh->gh_symndx;
+	t2 = maskwords = gh->gh_maskwords;
+	t3 = gh->gh_shift2;
+
+	src   += sizeof(Elf_GNU_Hash_Header);
+	srcsz -= sizeof(Elf_GNU_Hash_Header);
+	dsz   -= hdrsz;
+
+	sz = gh->gh_nbuckets * sizeof(uint32_t) + gh->gh_maskwords *
+	    sizeof(uint64_t);
+
+	if (srcsz < sz || dsz < sz)
+		return (0);
+
+	/* Write out the header. */
+	if (byteswap) {
+		SWAP_WORD(t0);
+		SWAP_WORD(t1);
+		SWAP_WORD(t2);
+		SWAP_WORD(t3);
+	}
+
+	WRITE_WORD(dst, t0);
+	WRITE_WORD(dst, t1);
+	WRITE_WORD(dst, t2);
+	WRITE_WORD(dst, t3);
+
+	/* Copy the bloom filter and the hash table. */
+	s64 = (uint64_t *) (uintptr_t) src;
+	for (n = 0; n < maskwords; n++) {
+		t64 = *s64++;
+		if (byteswap)
+			SWAP_XWORD(t64);
+		WRITE_WORD64(dst, t64);
+	}
+
+	s32 = (uint32_t *) s64;
+	for (n = 0; n < nbuckets; n++) {
+		t32 = *s32++;
+		if (byteswap)
+			SWAP_WORD(t32);
+		WRITE_WORD(dst, t32);
+	}
+
+	srcsz -= sz;
+	dsz   -= sz;
+
+	/* Copy out the hash chains. */
+	if (dsz < srcsz)
+		return (0);
+
+	nchains = srcsz / sizeof(uint32_t);
+	for (n = 0; n < nchains; n++) {
+		t32 = *s32++;
+		if (byteswap)
+			SWAP_WORD(t32);
+		WRITE_WORD(dst, t32);
+	}
+
+	return (1);
+}
+
+/*
+ * Elf_Note structures comprise a fixed size header followed by variable
+ * length strings.  The fixed size header needs to be byte swapped, but
+ * not the strings.
+ *
+ * Argument `count' denotes the total number of bytes to be converted.
+ * The destination buffer needs to be at least `count' bytes in size.
+ */
+static int
+_libelf_cvt_NOTE_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+	uint32_t namesz, descsz, type;
+	Elf_Note *en;
+	size_t sz, hdrsz;
+
+	if (dsz < count)	/* Destination buffer is too small. */
+		return (0);
+
+	hdrsz = 3 * sizeof(uint32_t);
+	if (count < hdrsz)		/* Source too small. */
+		return (0);
+
+	if (!byteswap) {
+		(void) memcpy(dst, src, count);
+		return (1);
+	}
+
+	/* Process all notes in the section. */
+	while (count > hdrsz) {
+		/* Read the note header. */
+		READ_WORD(src, namesz);
+		READ_WORD(src, descsz);
+		READ_WORD(src, type);
+
+		/* Translate. */
+		SWAP_WORD(namesz);
+		SWAP_WORD(descsz);
+		SWAP_WORD(type);
+
+		/* Copy out the translated note header. */
+		en = (Elf_Note *) (uintptr_t) dst;
+		en->n_namesz = namesz;
+		en->n_descsz = descsz;
+		en->n_type = type;
+
+		dsz -= sizeof(Elf_Note);
+		dst += sizeof(Elf_Note);
+		count -= hdrsz;
+
+		ROUNDUP2(namesz, 4U);
+		ROUNDUP2(descsz, 4U);
+
+		sz = namesz + descsz;
+
+		if (count < sz || dsz < sz)	/* Buffers are too small. */
+			return (0);
+
+		(void) memcpy(dst, src, sz);
+
+		src += sz;
+		dst += sz;
+
+		count -= sz;
+		dsz -= sz;
+	}
+
+	return (1);
+}
+
+static int
+_libelf_cvt_NOTE_tof(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+	uint32_t namesz, descsz, type;
+	Elf_Note *en;
+	size_t sz;
+
+	if (dsz < count)
+		return (0);
+
+	if (!byteswap) {
+		(void) memcpy(dst, src, count);
+		return (1);
+	}
+
+	while (count > sizeof(Elf_Note)) {
+
+		en = (Elf_Note *) (uintptr_t) src;
+		namesz = en->n_namesz;
+		descsz = en->n_descsz;
+		type = en->n_type;
+
+		sz = namesz;
+		ROUNDUP2(sz, 4U);
+		sz += descsz;
+		ROUNDUP2(sz, 4U);
+
+		SWAP_WORD(namesz);
+		SWAP_WORD(descsz);
+		SWAP_WORD(type);
+
+		WRITE_WORD(dst, namesz);
+		WRITE_WORD(dst, descsz);
+		WRITE_WORD(dst, type);
+
+		src += sizeof(Elf_Note);
+		count -= sizeof(Elf_Note);
+
+		if (count < sz)
+			sz = count;
+
+		(void) memcpy(dst, src, sz);
+
+		src += sz;
+		dst += sz;
+		count -= sz;
+	}
+
+	return (1);
+}
+
+struct converters {
+	int	(*tof32)(unsigned char *dst, size_t dsz, unsigned char *src,
+		    size_t cnt, int byteswap);
+	int	(*tom32)(unsigned char *dst, size_t dsz, unsigned char *src,
+		    size_t cnt, int byteswap);
+	int	(*tof64)(unsigned char *dst, size_t dsz, unsigned char *src,
+		    size_t cnt, int byteswap);
+	int	(*tom64)(unsigned char *dst, size_t dsz, unsigned char *src,
+		    size_t cnt, int byteswap);
+};
+
+
+static struct converters cvt[ELF_T_NUM] = {
+	/*[*/
+CONVERTER_NAMES(ELF_TYPE_LIST)
+	/*]*/
+
+	/*
+	 * Types that need hand-coded converters follow.
+	 */
+
+	[ELF_T_BYTE] = {
+		.tof32 = _libelf_cvt_BYTE_tox,
+		.tom32 = _libelf_cvt_BYTE_tox,
+		.tof64 = _libelf_cvt_BYTE_tox,
+		.tom64 = _libelf_cvt_BYTE_tox
+	},
+
+	[ELF_T_NOTE] = {
+		.tof32 = _libelf_cvt_NOTE_tof,
+		.tom32 = _libelf_cvt_NOTE_tom,
+		.tof64 = _libelf_cvt_NOTE_tof,
+		.tom64 = _libelf_cvt_NOTE_tom
+	}
+};
+
+int (*_libelf_get_translator(Elf_Type t, int direction, int elfclass))
+ (unsigned char *_dst, size_t dsz, unsigned char *_src, size_t _cnt,
+  int _byteswap)
+{
+	assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64);
+	assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY);
+
+	if (t >= ELF_T_NUM ||
+	    (elfclass != ELFCLASS32 && elfclass != ELFCLASS64) ||
+	    (direction != ELF_TOFILE && direction != ELF_TOMEMORY))
+		return (NULL);
+
+	return ((elfclass == ELFCLASS32) ?
+	    (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) :
+	    (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/libelf_data.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,101 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: libelf_data.c 3174 2015-03-27 17:13:41Z emaste $");
+
+int
+_libelf_xlate_shtype(uint32_t sht)
+{
+	/*
+	 * Look for known section types.
+	 */
+	switch (sht) {
+	case SHT_DYNAMIC:
+		return (ELF_T_DYN);
+	case SHT_DYNSYM:
+		return (ELF_T_SYM);
+	case SHT_FINI_ARRAY:
+		return (ELF_T_ADDR);
+	case SHT_GNU_HASH:
+		return (ELF_T_GNUHASH);
+	case SHT_GNU_LIBLIST:
+		return (ELF_T_WORD);
+	case SHT_GROUP:
+		return (ELF_T_WORD);
+	case SHT_HASH:
+		return (ELF_T_WORD);
+	case SHT_INIT_ARRAY:
+		return (ELF_T_ADDR);
+	case SHT_NOBITS:
+		return (ELF_T_BYTE);
+	case SHT_NOTE:
+		return (ELF_T_NOTE);
+	case SHT_PREINIT_ARRAY:
+		return (ELF_T_ADDR);
+	case SHT_PROGBITS:
+		return (ELF_T_BYTE);
+	case SHT_REL:
+		return (ELF_T_REL);
+	case SHT_RELA:
+		return (ELF_T_RELA);
+	case SHT_STRTAB:
+		return (ELF_T_BYTE);
+	case SHT_SYMTAB:
+		return (ELF_T_SYM);
+	case SHT_SYMTAB_SHNDX:
+		return (ELF_T_WORD);
+	case SHT_SUNW_dof:
+		return (ELF_T_BYTE);
+	case SHT_SUNW_move:
+		return (ELF_T_MOVE);
+	case SHT_SUNW_syminfo:
+		return (ELF_T_SYMINFO);
+	case SHT_SUNW_verdef:	/* == SHT_GNU_verdef */
+		return (ELF_T_VDEF);
+	case SHT_SUNW_verneed:	/* == SHT_GNU_verneed */
+		return (ELF_T_VNEED);
+	case SHT_SUNW_versym:	/* == SHT_GNU_versym */
+		return (ELF_T_HALF);
+	default:
+		/*
+		 * Values in the range [SHT_LOOS..SHT_HIUSER] (i.e.,
+		 * OS, processor and user-defined section types) are
+		 * legal, but since we do not know anything more about
+		 * their semantics, we return a type of ELF_T_BYTE.
+		 */
+		if (sht >= SHT_LOOS && sht <= SHT_HIUSER)
+			return (ELF_T_BYTE);
+
+		/*
+		 * Other values are unsupported.
+		 */
+		return (-1);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/libelf_ehdr.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,207 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <gelf.h>
+#include <libelf.h>
+#include <stdlib.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: libelf_ehdr.c 3575 2017-09-14 02:13:36Z emaste $");
+
+/*
+ * Retrieve counts for sections, phdrs and the section string table index
+ * from section header #0 of the ELF object.
+ */
+static int
+_libelf_load_extended(Elf *e, int ec, uint64_t shoff, uint16_t phnum,
+    uint16_t strndx)
+{
+	Elf_Scn *scn;
+	size_t fsz;
+	int (*xlator)(unsigned char *_d, size_t _dsz, unsigned char *_s,
+	    size_t _c, int _swap);
+	uint32_t shtype;
+
+	assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn));
+
+	fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, 1);
+	assert(fsz > 0);
+
+	if (e->e_rawsize < shoff + fsz) { /* raw file too small */
+		LIBELF_SET_ERROR(HEADER, 0);
+		return (0);
+	}
+
+	if ((scn = _libelf_allocate_scn(e, (size_t) 0)) == NULL)
+		return (0);
+
+	xlator = _libelf_get_translator(ELF_T_SHDR, ELF_TOMEMORY, ec);
+	(*xlator)((unsigned char *) &scn->s_shdr, sizeof(scn->s_shdr),
+	    (unsigned char *) e->e_rawfile + shoff, (size_t) 1,
+	    e->e_byteorder != LIBELF_PRIVATE(byteorder));
+
+#define	GET_SHDR_MEMBER(M) ((ec == ELFCLASS32) ? scn->s_shdr.s_shdr32.M : \
+		scn->s_shdr.s_shdr64.M)
+
+	if ((shtype = GET_SHDR_MEMBER(sh_type)) != SHT_NULL) {
+		LIBELF_SET_ERROR(SECTION, 0);
+		return (0);
+	}
+
+	e->e_u.e_elf.e_nscn = (size_t) GET_SHDR_MEMBER(sh_size);
+	e->e_u.e_elf.e_nphdr = (phnum != PN_XNUM) ? phnum :
+	    GET_SHDR_MEMBER(sh_info);
+	e->e_u.e_elf.e_strndx = (strndx != SHN_XINDEX) ? strndx :
+	    GET_SHDR_MEMBER(sh_link);
+#undef	GET_SHDR_MEMBER
+
+	return (1);
+}
+
+#define	EHDR_INIT(E,SZ)	 do {						\
+		Elf##SZ##_Ehdr *eh = (E);				\
+		eh->e_ident[EI_MAG0] = ELFMAG0;				\
+		eh->e_ident[EI_MAG1] = ELFMAG1;				\
+		eh->e_ident[EI_MAG2] = ELFMAG2;				\
+		eh->e_ident[EI_MAG3] = ELFMAG3;				\
+		eh->e_ident[EI_CLASS] = ELFCLASS##SZ;			\
+		eh->e_ident[EI_DATA]  = ELFDATANONE;			\
+		eh->e_ident[EI_VERSION] = LIBELF_PRIVATE(version) & 0xFFU; \
+		eh->e_machine = EM_NONE;				\
+		eh->e_type    = ELF_K_NONE;				\
+		eh->e_version = LIBELF_PRIVATE(version);		\
+	} while (0)
+
+void *
+_libelf_ehdr(Elf *e, int ec, int allocate)
+{
+	void *ehdr;
+	size_t fsz, msz;
+	uint16_t phnum, shnum, strndx;
+	uint64_t shoff;
+	int (*xlator)(unsigned char *_d, size_t _dsz, unsigned char *_s,
+	    size_t _c, int _swap);
+
+	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
+
+	if (e == NULL || e->e_kind != ELF_K_ELF) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	if (e->e_class != ELFCLASSNONE && e->e_class != ec) {
+		LIBELF_SET_ERROR(CLASS, 0);
+		return (NULL);
+	}
+
+	if (e->e_version != EV_CURRENT) {
+		LIBELF_SET_ERROR(VERSION, 0);
+		return (NULL);
+	}
+
+	if (e->e_class == ELFCLASSNONE)
+		e->e_class = ec;
+
+	if (ec == ELFCLASS32)
+		ehdr = (void *) e->e_u.e_elf.e_ehdr.e_ehdr32;
+	else
+		ehdr = (void *) e->e_u.e_elf.e_ehdr.e_ehdr64;
+
+	if (ehdr != NULL)	/* already have a translated ehdr */
+		return (ehdr);
+
+	fsz = _libelf_fsize(ELF_T_EHDR, ec, e->e_version, (size_t) 1);
+	assert(fsz > 0);
+
+	if (e->e_cmd != ELF_C_WRITE && e->e_rawsize < fsz) {
+		LIBELF_SET_ERROR(HEADER, 0);
+		return (NULL);
+	}
+
+	msz = _libelf_msize(ELF_T_EHDR, ec, EV_CURRENT);
+
+	assert(msz > 0);
+
+	if ((ehdr = calloc((size_t) 1, msz)) == NULL) {
+		LIBELF_SET_ERROR(RESOURCE, 0);
+		return (NULL);
+	}
+
+	if (ec == ELFCLASS32) {
+		e->e_u.e_elf.e_ehdr.e_ehdr32 = ehdr;
+		EHDR_INIT(ehdr,32);
+	} else {
+		e->e_u.e_elf.e_ehdr.e_ehdr64 = ehdr;
+		EHDR_INIT(ehdr,64);
+	}
+
+	if (allocate)
+		e->e_flags |= ELF_F_DIRTY;
+
+	if (e->e_cmd == ELF_C_WRITE)
+		return (ehdr);
+
+	xlator = _libelf_get_translator(ELF_T_EHDR, ELF_TOMEMORY, ec);
+	(*xlator)((unsigned char*) ehdr, msz, e->e_rawfile, (size_t) 1,
+	    e->e_byteorder != LIBELF_PRIVATE(byteorder));
+
+	if (ec == ELFCLASS32) {
+		phnum = ((Elf32_Ehdr *) ehdr)->e_phnum;
+		shnum = ((Elf32_Ehdr *) ehdr)->e_shnum;
+		shoff = ((Elf32_Ehdr *) ehdr)->e_shoff;
+		strndx = ((Elf32_Ehdr *) ehdr)->e_shstrndx;
+	} else {
+		phnum = ((Elf64_Ehdr *) ehdr)->e_phnum;
+		shnum = ((Elf64_Ehdr *) ehdr)->e_shnum;
+		shoff = ((Elf64_Ehdr *) ehdr)->e_shoff;
+		strndx = ((Elf64_Ehdr *) ehdr)->e_shstrndx;
+	}
+
+	if (shnum >= SHN_LORESERVE ||
+	    (shoff == 0LL && (shnum != 0 || phnum == PN_XNUM ||
+		strndx == SHN_XINDEX))) {
+		LIBELF_SET_ERROR(HEADER, 0);
+		return (NULL);
+	}
+
+	/*
+	 * If extended numbering is being used, read the correct
+	 * number of sections and program header entries.
+	 */
+	if ((shnum == 0 && shoff != 0) || phnum == PN_XNUM || strndx == SHN_XINDEX) {
+		if (_libelf_load_extended(e, ec, shoff, phnum, strndx) == 0)
+			return (NULL);
+	} else {
+		/* not using extended numbering */
+		e->e_u.e_elf.e_nphdr = phnum;
+		e->e_u.e_elf.e_nscn = shnum;
+		e->e_u.e_elf.e_strndx = strndx;
+	}
+
+	return (ehdr);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/libelf_extended.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,134 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: libelf_extended.c 3174 2015-03-27 17:13:41Z emaste $");
+
+/*
+ * Retrieve section #0, allocating a new section if needed.
+ */
+static Elf_Scn *
+_libelf_getscn0(Elf *e)
+{
+	Elf_Scn *s;
+
+	if ((s = STAILQ_FIRST(&e->e_u.e_elf.e_scn)) != NULL)
+		return (s);
+
+	return (_libelf_allocate_scn(e, (size_t) SHN_UNDEF));
+}
+
+int
+_libelf_setshnum(Elf *e, void *eh, int ec, size_t shnum)
+{
+	Elf_Scn *scn;
+
+	if (shnum >= SHN_LORESERVE) {
+		if ((scn = _libelf_getscn0(e)) == NULL)
+			return (0);
+
+		assert(scn->s_ndx == SHN_UNDEF);
+
+		if (ec == ELFCLASS32)
+			scn->s_shdr.s_shdr32.sh_size = shnum;
+		else
+			scn->s_shdr.s_shdr64.sh_size = shnum;
+
+		(void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY);
+
+		shnum = 0;
+	}
+
+	if (ec == ELFCLASS32)
+		((Elf32_Ehdr *) eh)->e_shnum = shnum & 0xFFFFU;
+	else
+		((Elf64_Ehdr *) eh)->e_shnum = shnum & 0xFFFFU;
+
+
+	return (1);
+}
+
+int
+_libelf_setshstrndx(Elf *e, void *eh, int ec, size_t shstrndx)
+{
+	Elf_Scn *scn;
+
+	if (shstrndx >= SHN_LORESERVE) {
+		if ((scn = _libelf_getscn0(e)) == NULL)
+			return (0);
+
+		assert(scn->s_ndx == SHN_UNDEF);
+
+		if (ec == ELFCLASS32)
+			scn->s_shdr.s_shdr32.sh_link = shstrndx;
+		else
+			scn->s_shdr.s_shdr64.sh_link = shstrndx;
+
+		(void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY);
+
+		shstrndx = SHN_XINDEX;
+	}
+
+	if (ec == ELFCLASS32)
+		((Elf32_Ehdr *) eh)->e_shstrndx = shstrndx & 0xFFFFU;
+	else
+		((Elf64_Ehdr *) eh)->e_shstrndx = shstrndx & 0xFFFFU;
+
+	return (1);
+}
+
+int
+_libelf_setphnum(Elf *e, void *eh, int ec, size_t phnum)
+{
+	Elf_Scn *scn;
+
+	if (phnum >= PN_XNUM) {
+		if ((scn = _libelf_getscn0(e)) == NULL)
+			return (0);
+
+		assert(scn->s_ndx == SHN_UNDEF);
+
+		if (ec == ELFCLASS32)
+			scn->s_shdr.s_shdr32.sh_info = phnum;
+		else
+			scn->s_shdr.s_shdr64.sh_info = phnum;
+
+		(void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY);
+
+		phnum = PN_XNUM;
+	}
+
+	if (ec == ELFCLASS32)
+		((Elf32_Ehdr *) eh)->e_phnum = phnum & 0xFFFFU;
+	else
+		((Elf64_Ehdr *) eh)->e_phnum = phnum & 0xFFFFU;
+
+	return (1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/libelf_fsize.m4	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,159 @@
+/*-
+ * Copyright (c) 2006,2008-2011 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: libelf_fsize.m4 2225 2011-11-26 18:55:54Z jkoshy $");
+
+/* WARNING: GENERATED FROM __file__. */
+
+/*
+ * Create an array of file sizes from the elf_type definitions
+ */
+
+divert(-1)
+include(SRCDIR`/elf_types.m4')
+
+/*
+ * Translations from structure definitions to the size of their file
+ * representations.
+ */
+
+/* `Basic' types. */
+define(`BYTE_SIZE',	1)
+define(`IDENT_SIZE',	`EI_NIDENT')
+
+/* Types that have variable length. */
+define(`GNUHASH_SIZE',	1)
+define(`NOTE_SIZE',	1)
+define(`VDEF_SIZE',	1)
+define(`VNEED_SIZE',	1)
+
+/* Currently unimplemented types. */
+define(`MOVEP_SIZE',	0)
+
+/* Overrides for 32 bit types that do not exist. */
+define(`XWORD_SIZE32',	0)
+define(`SXWORD_SIZE32',	0)
+
+/*
+ * FSZ{32,64} define the sizes of 32 and 64 bit file structures respectively.
+ */
+
+define(`FSZ32',`_FSZ32($1_DEF)')
+define(`_FSZ32',
+  `ifelse($#,1,0,
+    `_BSZ32($1)+_FSZ32(shift($@))')')
+define(`_BSZ32',`$2_SIZE32')
+
+define(`FSZ64',`_FSZ64($1_DEF)')
+define(`_FSZ64',
+  `ifelse($#,1,0,
+    `_BSZ64($1)+_FSZ64(shift($@))')')
+define(`_BSZ64',`$2_SIZE64')
+
+/*
+ * DEFINE_ELF_FSIZES(TYPE,NAME)
+ *
+ * Shorthand for defining  for 32 and 64 versions
+ * of elf type TYPE.
+ *
+ * If TYPE`'_SIZE is defined, use its value for both 32 bit and 64 bit
+ * sizes.
+ *
+ * Otherwise, look for a explicit 32/64 bit size definition for TYPE,
+ * TYPE`'_SIZE32 or TYPE`'_SIZE64. If this definition is present, there
+ * is nothing further to do.
+ *
+ * Otherwise, if an Elf{32,64}_`'NAME structure definition is known,
+ * compute an expression that adds up the sizes of the structure's
+ * constituents.
+ *
+ * If such a structure definition is not known, treat TYPE as a primitive
+ * (i.e., integral) type and use sizeof(Elf{32,64}_`'NAME) to get its
+ * file representation size.
+ */
+
+define(`DEFINE_ELF_FSIZE',
+  `ifdef($1`_SIZE',
+    `define($1_SIZE32,$1_SIZE)
+     define($1_SIZE64,$1_SIZE)',
+    `ifdef($1`_SIZE32',`',
+      `ifdef(`Elf32_'$2`_DEF',
+        `define($1_SIZE32,FSZ32(Elf32_$2))',
+        `define($1_SIZE32,`sizeof(Elf32_'$2`)')')')
+     ifdef($1`_SIZE64',`',
+      `ifdef(`Elf64_'$2`_DEF',
+        `define($1_SIZE64,FSZ64(Elf64_$2))',
+        `define($1_SIZE64,`sizeof(Elf64_'$2`)')')')')')
+
+define(`DEFINE_ELF_FSIZES',
+  `ifelse($#,1,`',
+    `DEFINE_ELF_FSIZE($1)
+     DEFINE_ELF_FSIZES(shift($@))')')
+
+DEFINE_ELF_FSIZES(ELF_TYPE_LIST)
+DEFINE_ELF_FSIZE(`IDENT',`')	# `IDENT' is a pseudo type
+
+define(`FSIZE',
+  `[ELF_T_$1] = { .fsz32 = $1_SIZE32, .fsz64 = $1_SIZE64 },
+')
+define(`FSIZES',
+  `ifelse($#,1,`',
+    `FSIZE($1)
+FSIZES(shift($@))')')
+
+divert(0)
+
+struct fsize {
+	size_t fsz32;
+	size_t fsz64;
+};
+
+static struct fsize fsize[ELF_T_NUM] = {
+FSIZES(ELF_TYPE_LIST)
+};
+
+size_t
+_libelf_fsize(Elf_Type t, int ec, unsigned int v, size_t c)
+{
+	size_t sz;
+
+	sz = 0;
+	if (v != EV_CURRENT)
+		LIBELF_SET_ERROR(VERSION, 0);
+	else if ((int) t < ELF_T_FIRST || t > ELF_T_LAST)
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+	else {
+		sz = ec == ELFCLASS64 ? fsize[t].fsz64 : fsize[t].fsz32;
+		if (sz == 0)
+			LIBELF_SET_ERROR(UNIMPL, 0);
+	}
+
+	return (sz*c);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/libelf_memory.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,96 @@
+/*-
+ * Copyright (c) 2011 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <ar.h>
+#include <assert.h>
+#include <string.h>
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: libelf_memory.c 3013 2014-03-23 06:16:59Z jkoshy $");
+
+/*
+ * Create an ELF descriptor for a memory image, optionally reporting
+ * parse errors.
+ */
+
+Elf *
+_libelf_memory(unsigned char *image, size_t sz, int reporterror)
+{
+	Elf *e;
+	int e_class;
+	enum Elf_Error error;
+	unsigned int e_byteorder, e_version;
+
+	assert(image != NULL);
+	assert(sz > 0);
+
+	if ((e = _libelf_allocate_elf()) == NULL)
+		return (NULL);
+
+	e->e_cmd = ELF_C_READ;
+	e->e_rawfile = image;
+	e->e_rawsize = sz;
+
+#undef	LIBELF_IS_ELF
+#define	LIBELF_IS_ELF(P) ((P)[EI_MAG0] == ELFMAG0 && 		\
+	(P)[EI_MAG1] == ELFMAG1 && (P)[EI_MAG2] == ELFMAG2 &&	\
+	(P)[EI_MAG3] == ELFMAG3)
+
+	if (sz > EI_NIDENT && LIBELF_IS_ELF(image)) {
+		e_byteorder = image[EI_DATA];
+		e_class     = image[EI_CLASS];
+		e_version   = image[EI_VERSION];
+
+		error = ELF_E_NONE;
+
+		if (e_version > EV_CURRENT)
+			error = ELF_E_VERSION;
+		else if ((e_byteorder != ELFDATA2LSB && e_byteorder !=
+ 		    ELFDATA2MSB) || (e_class != ELFCLASS32 && e_class !=
+		    ELFCLASS64))
+			error = ELF_E_HEADER;
+
+		if (error != ELF_E_NONE) {
+			if (reporterror) {
+				LIBELF_PRIVATE(error) = LIBELF_ERROR(error, 0);
+				(void) _libelf_release_elf(e);
+				return (NULL);
+			}
+		} else {
+			_libelf_init_elf(e, ELF_K_ELF);
+
+			e->e_byteorder = e_byteorder;
+			e->e_class = e_class;
+			e->e_version = e_version;
+		}
+	} else if (sz >= SARMAG &&
+	    strncmp((const char *) image, ARMAG, (size_t) SARMAG) == 0)
+		return (_libelf_ar_open(e, reporterror));
+
+	return (e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/libelf_msize.m4	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,106 @@
+/*-
+ * Copyright (c) 2006,2008-2011 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <libelf.h>
+#include <string.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: libelf_msize.m4 3174 2015-03-27 17:13:41Z emaste $");
+
+/* WARNING: GENERATED FROM __file__. */
+
+struct msize {
+	size_t	msz32;
+	size_t	msz64;
+};
+
+divert(-1)
+include(SRCDIR`/elf_types.m4')
+
+/*
+ * ELF types whose memory representations have a variable size.
+ */
+define(BYTE_SIZE,	1)
+define(GNUHASH_SIZE,	1)
+define(NOTE_SIZE,	1)
+define(VDEF_SIZE,	1)
+define(VNEED_SIZE,	1)
+
+/*
+ * Unimplemented types.
+ */
+define(MOVEP_SIZE,	0)
+define(SXWORD_SIZE32,	0)
+define(XWORD_SIZE32,	0)
+
+define(`DEFINE_ELF_MSIZE',
+  `ifdef($1`_SIZE',
+    `define($1_SIZE32,$1_SIZE)
+     define($1_SIZE64,$1_SIZE)',
+    `ifdef($1`_SIZE32',`',
+      `define($1_SIZE32,sizeof(Elf32_$2))')
+     ifdef($1`_SIZE64',`',
+      `define($1_SIZE64,sizeof(Elf64_$2))')')')
+define(`DEFINE_ELF_MSIZES',
+  `ifelse($#,1,`',
+    `DEFINE_ELF_MSIZE($1)
+     DEFINE_ELF_MSIZES(shift($@))')')
+
+DEFINE_ELF_MSIZES(ELF_TYPE_LIST)
+
+define(`MSIZE',
+  `[ELF_T_$1] = { .msz32 = $1_SIZE32, .msz64 = $1_SIZE64 },
+')
+define(`MSIZES',
+  `ifelse($#,1,`',
+    `MSIZE($1)
+MSIZES(shift($@))')')
+
+divert(0)
+
+static struct msize msize[ELF_T_NUM] = {
+MSIZES(ELF_TYPE_LIST)
+};
+
+size_t
+_libelf_msize(Elf_Type t, int elfclass, unsigned int version)
+{
+	size_t sz;
+
+	assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64);
+	assert((signed) t >= ELF_T_FIRST && t <= ELF_T_LAST);
+
+	if (version != EV_CURRENT) {
+		LIBELF_SET_ERROR(VERSION, 0);
+		return (0);
+	}
+
+	sz = (elfclass == ELFCLASS32) ? msize[t].msz32 : msize[t].msz64;
+
+	return (sz);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/libelf_open.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,249 @@
+/*-
+ * Copyright (c) 2006,2008-2011 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <libelf.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "_libelf.h"
+
+#if	ELFTC_HAVE_MMAP
+#include <sys/mman.h>
+#endif
+
+ELFTC_VCSID("$Id: libelf_open.c 3007 2014-03-22 08:10:14Z jkoshy $");
+
+#define	_LIBELF_INITSIZE	(64*1024)
+
+/*
+ * Read from a device file, pipe or socket.
+ */
+static void *
+_libelf_read_special_file(int fd, size_t *fsz)
+{
+	ssize_t readsz;
+	size_t bufsz, datasz;
+	unsigned char *buf, *t;
+
+	datasz = 0;
+	readsz = 0;
+	bufsz = _LIBELF_INITSIZE;
+	if ((buf = malloc(bufsz)) == NULL)
+		goto resourceerror;
+
+	/*
+	 * Read data from the file descriptor till we reach EOF, or
+	 * till an error is encountered.
+	 */
+	do {
+		/* Check if we need to expand the data buffer. */
+		if (datasz == bufsz) {
+			bufsz *= 2;
+			if ((t = realloc(buf, bufsz)) == NULL)
+				goto resourceerror;
+			buf = t;
+		}
+
+		do {
+			assert(bufsz - datasz > 0);
+			t = buf + datasz;
+			if ((readsz = read(fd, t, bufsz - datasz)) <= 0)
+				break;
+			datasz += (size_t) readsz;
+		} while (datasz < bufsz);
+
+	} while (readsz > 0);
+
+	if (readsz < 0) {
+		LIBELF_SET_ERROR(IO, errno);
+		goto error;
+	}
+
+	assert(readsz == 0);
+
+	/*
+	 * Free up extra buffer space.
+	 */
+	if (bufsz > datasz) {
+		if (datasz > 0) {
+			if ((t = realloc(buf, datasz)) == NULL)
+				goto resourceerror;
+			buf = t;
+		} else {	/* Zero bytes read. */
+			LIBELF_SET_ERROR(ARGUMENT, 0);
+			free(buf);
+			buf = NULL;
+		}
+	}
+
+	*fsz = datasz;
+	return (buf);
+
+resourceerror:
+	LIBELF_SET_ERROR(RESOURCE, 0);
+error:
+	if (buf != NULL)
+		free(buf);
+	return (NULL);
+}
+
+/*
+ * Read the contents of the file referenced by the file descriptor
+ * 'fd'.
+ */
+
+Elf *
+_libelf_open_object(int fd, Elf_Cmd c, int reporterror)
+{
+	Elf *e;
+	void *m;
+	mode_t mode;
+	size_t fsize;
+	struct stat sb;
+	unsigned int flags;
+
+	assert(c == ELF_C_READ || c == ELF_C_RDWR || c == ELF_C_WRITE);
+
+	if (fstat(fd, &sb) < 0) {
+		LIBELF_SET_ERROR(IO, errno);
+		return (NULL);
+	}
+
+	mode = sb.st_mode;
+	fsize = (size_t) sb.st_size;
+
+	/*
+	 * Reject unsupported file types.
+	 */
+	if (!S_ISREG(mode) && !S_ISCHR(mode) && !S_ISFIFO(mode) &&
+	    !S_ISSOCK(mode)) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	/*
+	 * For ELF_C_WRITE mode, allocate and return a descriptor.
+	 */
+	if (c == ELF_C_WRITE) {
+		if ((e = _libelf_allocate_elf()) != NULL) {
+			_libelf_init_elf(e, ELF_K_ELF);
+			e->e_byteorder = LIBELF_PRIVATE(byteorder);
+			e->e_fd = fd;
+			e->e_cmd = c;
+			if (!S_ISREG(mode))
+				e->e_flags |= LIBELF_F_SPECIAL_FILE;
+		}
+
+		return (e);
+	}
+
+
+	/*
+	 * ELF_C_READ and ELF_C_RDWR mode.
+	 */
+	m = NULL;
+	flags = 0;
+	if (S_ISREG(mode)) {
+
+		/*
+		 * Reject zero length files.
+		 */
+		if (fsize == 0) {
+			LIBELF_SET_ERROR(ARGUMENT, 0);
+			return (NULL);
+		}
+
+#if	ELFTC_HAVE_MMAP
+		/*
+		 * Always map regular files in with 'PROT_READ'
+		 * permissions.
+		 *
+		 * For objects opened in ELF_C_RDWR mode, when
+		 * elf_update(3) is called, we remove this mapping,
+		 * write file data out using write(2), and map the new
+		 * contents back.
+		 */
+		m = mmap(NULL, fsize, PROT_READ, MAP_PRIVATE, fd, (off_t) 0);
+
+		if (m == MAP_FAILED)
+			m = NULL;
+		else
+			flags = LIBELF_F_RAWFILE_MMAP;
+#endif
+
+		/*
+		 * Fallback to a read() if the call to mmap() failed,
+		 * or if mmap() is not available.
+		 */
+		if (m == NULL) {
+			if ((m = malloc(fsize)) == NULL) {
+				LIBELF_SET_ERROR(RESOURCE, 0);
+				return (NULL);
+			}
+
+			if (read(fd, m, fsize) != (ssize_t) fsize) {
+				LIBELF_SET_ERROR(IO, errno);
+				free(m);
+				return (NULL);
+			}
+
+			flags = LIBELF_F_RAWFILE_MALLOC;
+		}
+	} else if ((m = _libelf_read_special_file(fd, &fsize)) != NULL)
+		flags = LIBELF_F_RAWFILE_MALLOC | LIBELF_F_SPECIAL_FILE;
+	else
+		return (NULL);
+
+	if ((e = _libelf_memory(m, fsize, reporterror)) == NULL) {
+		assert((flags & LIBELF_F_RAWFILE_MALLOC) ||
+		    (flags & LIBELF_F_RAWFILE_MMAP));
+		if (flags & LIBELF_F_RAWFILE_MALLOC)
+			free(m);
+#if	ELFTC_HAVE_MMAP
+		else
+			(void) munmap(m, fsize);
+#endif
+		return (NULL);
+	}
+
+	/* ar(1) archives aren't supported in RDWR mode. */
+	if (c == ELF_C_RDWR && e->e_kind == ELF_K_AR) {
+		(void) elf_end(e);
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	e->e_flags |= flags;
+	e->e_fd = fd;
+	e->e_cmd = c;
+
+	return (e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/libelf_phdr.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,153 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <gelf.h>
+#include <libelf.h>
+#include <stdlib.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: libelf_phdr.c 3174 2015-03-27 17:13:41Z emaste $");
+
+void *
+_libelf_getphdr(Elf *e, int ec)
+{
+	size_t phnum;
+	size_t fsz, msz;
+	uint64_t phoff;
+	Elf32_Ehdr *eh32;
+	Elf64_Ehdr *eh64;
+	void *ehdr, *phdr;
+	int (*xlator)(unsigned char *_d, size_t _dsz, unsigned char *_s,
+	    size_t _c, int _swap);
+
+	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
+
+	if (e == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	if ((phdr = (ec == ELFCLASS32 ?
+		 (void *) e->e_u.e_elf.e_phdr.e_phdr32 :
+		 (void *) e->e_u.e_elf.e_phdr.e_phdr64)) != NULL)
+		return (phdr);
+
+	/*
+	 * Check the PHDR related fields in the EHDR for sanity.
+	 */
+
+	if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL)
+		return (NULL);
+
+	phnum = e->e_u.e_elf.e_nphdr;
+
+	if (ec == ELFCLASS32) {
+		eh32      = (Elf32_Ehdr *) ehdr;
+		phoff     = (uint64_t) eh32->e_phoff;
+	} else {
+		eh64      = (Elf64_Ehdr *) ehdr;
+		phoff     = (uint64_t) eh64->e_phoff;
+	}
+
+	fsz = gelf_fsize(e, ELF_T_PHDR, phnum, e->e_version);
+
+	assert(fsz > 0);
+
+	if ((uint64_t) e->e_rawsize < (phoff + fsz)) {
+		LIBELF_SET_ERROR(HEADER, 0);
+		return (NULL);
+	}
+
+	msz = _libelf_msize(ELF_T_PHDR, ec, EV_CURRENT);
+
+	assert(msz > 0);
+
+	if ((phdr = calloc(phnum, msz)) == NULL) {
+		LIBELF_SET_ERROR(RESOURCE, 0);
+		return (NULL);
+	}
+
+	if (ec == ELFCLASS32)
+		e->e_u.e_elf.e_phdr.e_phdr32 = phdr;
+	else
+		e->e_u.e_elf.e_phdr.e_phdr64 = phdr;
+
+
+	xlator = _libelf_get_translator(ELF_T_PHDR, ELF_TOMEMORY, ec);
+	(*xlator)(phdr, phnum * msz, e->e_rawfile + phoff, phnum,
+	    e->e_byteorder != LIBELF_PRIVATE(byteorder));
+
+	return (phdr);
+}
+
+void *
+_libelf_newphdr(Elf *e, int ec, size_t count)
+{
+	void *ehdr, *newphdr, *oldphdr;
+	size_t msz;
+
+	if (e == NULL) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) {
+		LIBELF_SET_ERROR(SEQUENCE, 0);
+		return (NULL);
+	}
+
+	assert(e->e_class == ec);
+	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
+	assert(e->e_version == EV_CURRENT);
+
+	msz = _libelf_msize(ELF_T_PHDR, ec, e->e_version);
+
+	assert(msz > 0);
+
+	newphdr = NULL;
+	if (count > 0 && (newphdr = calloc(count, msz)) == NULL) {
+		LIBELF_SET_ERROR(RESOURCE, 0);
+		return (NULL);
+	}
+
+	if (ec == ELFCLASS32) {
+		if ((oldphdr = (void *) e->e_u.e_elf.e_phdr.e_phdr32) != NULL)
+			free(oldphdr);
+		e->e_u.e_elf.e_phdr.e_phdr32 = (Elf32_Phdr *) newphdr;
+	} else {
+		if ((oldphdr = (void *) e->e_u.e_elf.e_phdr.e_phdr64) != NULL)
+			free(oldphdr);
+		e->e_u.e_elf.e_phdr.e_phdr64 = (Elf64_Phdr *) newphdr;
+	}
+
+	e->e_u.e_elf.e_nphdr = count;
+
+	elf_flagphdr(e, ELF_C_SET, ELF_F_DIRTY);
+
+	return (newphdr);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/libelf_shdr.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <gelf.h>
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: libelf_shdr.c 3174 2015-03-27 17:13:41Z emaste $");
+
+void *
+_libelf_getshdr(Elf_Scn *s, int ec)
+{
+	Elf *e;
+
+	if (s == NULL || (e = s->s_elf) == NULL ||
+	    e->e_kind != ELF_K_ELF) {
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	if (ec == ELFCLASSNONE)
+		ec = e->e_class;
+
+	if (ec != e->e_class) {
+		LIBELF_SET_ERROR(CLASS, 0);
+		return (NULL);
+	}
+
+	return ((void *) &s->s_shdr);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/libelf_xlate.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,148 @@
+/*-
+ * Copyright (c) 2006,2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <libelf.h>
+
+#include "_libelf.h"
+
+ELFTC_VCSID("$Id: libelf_xlate.c 3174 2015-03-27 17:13:41Z emaste $");
+
+/*
+ * Translate to/from the file representation of ELF objects.
+ *
+ * Translation could potentially involve the following
+ * transformations:
+ *
+ * - an endianness conversion,
+ * - a change of layout, as the file representation of ELF objects
+ *   can differ from their in-memory representation.
+ * - a change in representation due to a layout version change.
+ */
+
+Elf_Data *
+_libelf_xlate(Elf_Data *dst, const Elf_Data *src, unsigned int encoding,
+    int elfclass, int direction)
+{
+	int byteswap;
+	size_t cnt, dsz, fsz, msz;
+	uintptr_t sb, se, db, de;
+
+	if (encoding == ELFDATANONE)
+		encoding = LIBELF_PRIVATE(byteorder);
+
+	if ((encoding != ELFDATA2LSB && encoding != ELFDATA2MSB) ||
+	    dst == NULL || src == NULL || dst == src)	{
+		LIBELF_SET_ERROR(ARGUMENT, 0);
+		return (NULL);
+	}
+
+	assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64);
+	assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY);
+
+	if (dst->d_version != src->d_version) {
+		LIBELF_SET_ERROR(UNIMPL, 0);
+		return (NULL);
+	}
+
+	if  (src->d_buf == NULL || dst->d_buf == NULL) {
+		LIBELF_SET_ERROR(DATA, 0);
+		return (NULL);
+	}
+
+	if ((int) src->d_type < 0 || src->d_type >= ELF_T_NUM) {
+		LIBELF_SET_ERROR(DATA, 0);
+		return (NULL);
+	}
+
+	if ((fsz = (elfclass == ELFCLASS32 ? elf32_fsize : elf64_fsize)
+	    (src->d_type, (size_t) 1, src->d_version)) == 0)
+		return (NULL);
+
+	msz = _libelf_msize(src->d_type, elfclass, src->d_version);
+
+	assert(msz > 0);
+
+	if (src->d_size % (direction == ELF_TOMEMORY ? fsz : msz)) {
+		LIBELF_SET_ERROR(DATA, 0);
+		return (NULL);
+	}
+
+	/*
+	 * Determine the number of objects that need to be converted, and
+	 * the space required for the converted objects in the destination
+	 * buffer.
+	 */
+	if (direction == ELF_TOMEMORY) {
+		cnt = (size_t) src->d_size / fsz;
+		dsz = cnt * msz;
+	} else {
+		cnt = (size_t) src->d_size / msz;
+		dsz = cnt * fsz;
+	}
+
+	if (dst->d_size  <  dsz) {
+		LIBELF_SET_ERROR(DATA, 0);
+		return (NULL);
+	}
+
+	sb = (uintptr_t) src->d_buf;
+	se = sb + (size_t) src->d_size;
+	db = (uintptr_t) dst->d_buf;
+	de = db + (size_t) dst->d_size;
+
+	/*
+	 * Check for overlapping buffers.  Note that db == sb is
+	 * allowed.
+	 */
+	if (db != sb && de > sb && se > db) {
+		LIBELF_SET_ERROR(DATA, 0);
+		return (NULL);
+	}
+
+	if ((direction == ELF_TOMEMORY ? db : sb) %
+	    _libelf_malign(src->d_type, elfclass)) {
+		LIBELF_SET_ERROR(DATA, 0);
+		return (NULL);
+	}
+
+	dst->d_type = src->d_type;
+	dst->d_size = dsz;
+
+	byteswap = encoding != LIBELF_PRIVATE(byteorder);
+
+	if (src->d_size == 0 ||
+	    (db == sb && !byteswap && fsz == msz))
+		return (dst);	/* nothing more to do */
+
+	if (!(_libelf_get_translator(src->d_type, direction, elfclass))
+	    (dst->d_buf, dsz, src->d_buf, cnt, byteswap)) {
+		LIBELF_SET_ERROR(DATA, 0);
+		return (NULL);
+	}
+
+	return (dst);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/os.FreeBSD.mk	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,7 @@
+#
+# Building for a FreeBSD target.
+#
+# $Id: os.FreeBSD.mk 710 2010-02-17 14:21:38Z jkoshy $
+
+# Symbol versioning support [FreeBSD 7.X and later]
+VERSION_MAP=		${.CURDIR}/Version.map
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelf/os.NetBSD.mk	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,7 @@
+#
+# Build recipes for NetBSD.
+#
+# $Id: os.NetBSD.mk 710 2010-02-17 14:21:38Z jkoshy $
+#
+
+MKLINT=		no		# lint dies with a sigbus
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/Makefile	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,60 @@
+# $Id: Makefile 3601 2018-04-12 16:58:53Z jkoshy $
+
+TOP=	..
+
+LIB=	elftc
+
+SRCS=	elftc_bfdtarget.c			\
+	elftc_copyfile.c			\
+	elftc_demangle.c			\
+	elftc_reloc_type_str.c			\
+	elftc_set_timestamps.c			\
+	elftc_string_table.c			\
+	elftc_timestamp.c			\
+	elftc_version.c				\
+	libelftc_bfdtarget.c			\
+	libelftc_dem_arm.c			\
+	libelftc_dem_gnu2.c			\
+	libelftc_dem_gnu3.c			\
+	libelftc_hash.c				\
+	libelftc_vstr.c
+
+INCS=		libelftc.h
+INCSDIR=	/usr/include
+
+RELEASE=	HEAD		# Change this on release branches.
+
+SHLIB_MAJOR=	1
+
+WARNS?=	6
+
+ELFTC_VERSION_FILE=	${.OBJDIR}/elftc_version.c
+CLEANFILES+=		${ELFTC_VERSION_FILE}
+
+LDADD+=	-lelf
+
+MAN=	elftc.3 \
+	elftc_bfd_find_target.3 \
+	elftc_copyfile.3 \
+	elftc_demangle.3 \
+	elftc_reloc_type_str.3 \
+	elftc_set_timestamps.3 \
+	elftc_string_table_create.3 \
+	elftc_version.3
+
+MLINKS=	elftc_bfd_find_target.3 elftc_bfd_target_byteorder.3 \
+	elftc_bfd_find_target.3 elftc_bfd_target_class.3 \
+	elftc_bfd_find_target.3 elftc_bfd_target_flavor.3 \
+	elftc_string_table_create.3 elftc_string_table_from_section.3 \
+	elftc_string_table_create.3 elftc_string_table_destroy.3 \
+	elftc_string_table_create.3 elftc_string_table_image.3 \
+	elftc_string_table_create.3 elftc_string_table_insert.3 \
+	elftc_string_table_create.3 elftc_string_table_lookup.3
+
+.if	!make(clean) && !make(clobber) && !make(obj)
+.BEGIN:	.SILENT
+	${.CURDIR}/make-toolchain-version -t ${.CURDIR}/${TOP} \
+	    -r ${RELEASE} -h ${OS_HOST} -o ${ELFTC_VERSION_FILE}
+.endif
+
+.include "${TOP}/mk/elftoolchain.lib.mk"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/Version.map	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,18 @@
+/*
+ * $Id: Version.map 2574 2012-09-11 15:11:59Z jkoshy $
+ */
+
+R1.0 {
+global:
+	elftc_bfd_find_target;
+	elftc_bfd_target_byteorder;
+	elftc_bfd_target_class;
+	elftc_bfd_target_flavor;
+	elftc_bfd_target_machine;
+	elftc_copyfile;
+	elftc_demangle;
+	elftc_set_timestamps;
+	elftc_version;
+local:
+	*;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/_libelftc.h	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,95 @@
+/*-
+ * Copyright (c) 2009 Kai Wang
+ * Copyright (c) 2007,2008 Hyogeol Lee <hyogeollee@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: _libelftc.h 3531 2017-06-05 05:08:43Z kaiwang27 $
+ */
+
+#ifndef	__LIBELFTC_H_
+#define	__LIBELFTC_H_
+
+#include <stdbool.h>
+
+#include "_elftc.h"
+
+struct _Elftc_Bfd_Target {
+	const char	*bt_name;	/* target name. */
+	unsigned int	 bt_type;	/* target type. */
+	unsigned int	 bt_byteorder;	/* elf target byteorder. */
+	unsigned int	 bt_elfclass;	/* elf target class (32/64bit). */
+	unsigned int	 bt_machine;	/* elf target arch. */
+	unsigned int	 bt_osabi;	/* elf target abi. */
+};
+
+extern struct _Elftc_Bfd_Target _libelftc_targets[];
+
+/** @brief Dynamic vector data for string. */
+struct vector_str {
+	/** Current size */
+	size_t		size;
+	/** Total capacity */
+	size_t		capacity;
+	/** String array */
+	char		**container;
+};
+
+#define BUFFER_GROWFACTOR	1.618
+
+#define	ELFTC_FAILURE		0
+#define	ELFTC_ISDIGIT(C) 	(isdigit((C) & 0xFF))
+#define	ELFTC_SUCCESS		1
+
+#define VECTOR_DEF_CAPACITY	8
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+char	*cpp_demangle_ARM(const char *_org);
+char	*cpp_demangle_gnu2(const char *_org);
+char	*cpp_demangle_gnu3(const char *_org);
+bool	is_cpp_mangled_ARM(const char *_org);
+bool	is_cpp_mangled_gnu2(const char *_org);
+bool	is_cpp_mangled_gnu3(const char *_org);
+unsigned int	libelftc_hash_string(const char *);
+void	vector_str_dest(struct vector_str *_vec);
+int	vector_str_find(const struct vector_str *_vs, const char *_str,
+    size_t _len);
+char	*vector_str_get_flat(const struct vector_str *_vs, size_t *_len);
+bool	vector_str_init(struct vector_str *_vs);
+bool	vector_str_pop(struct vector_str *_vs);
+bool	vector_str_push(struct vector_str *_vs, const char *_str,
+    size_t _len);
+bool	vector_str_push_vector(struct vector_str *_dst,
+    struct vector_str *_org);
+bool	vector_str_push_vector_head(struct vector_str *_dst,
+    struct vector_str *_org);
+char	*vector_str_substr(const struct vector_str *_vs, size_t _begin,
+    size_t _end, size_t *_rlen);
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* __LIBELFTC_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/elftc.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,83 @@
+.\" Copyright (c) 2012 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elftc.3 2818 2012-12-24 12:32:48Z jkoshy $
+.\"
+.Dd December 24, 2012
+.Os
+.Dt ELFTC 3
+.Sh NAME
+.Nm elftc
+.Nd support routines used in the Elftoolchain project
+.Sh LIBRARY
+.Lb libelftc
+.Sh SYNOPSIS
+.In libelftc.h
+.Sh DESCRIPTION
+The
+.Lb libelftc
+provides support routines used for developing the utilities in the
+Elftoolchain source tree.
+.Pp
+This manual page serves as an overview of the functionality in this
+library.
+Additional reference information may be found in the individual
+manual pages for the functions listed below.
+.Ss Functional Grouping
+.Bl -tag -width indent
+.It "Binary Object Handling"
+.Bl -tag -compact
+.It Fn elftc_bfd_find_target
+Locate a binary object descriptor.
+.It Fn elftc_bfd_target_class
+Query the ELF class for a binary object descriptor.
+.It Fn elftc_bfd_target_byteorder
+Query the byte order for a binary object descriptor.
+.It Fn elftc_bfd_target_flavor
+Query the object format for a binary object descriptor.
+.It Fn elftc_bfd_target_machine
+Query the target machine for a binary object descriptor.
+.El
+.It "C++ support"
+.Bl -tag -compact
+.It Fn elftc_demangle
+Decodes a symbol name encoded according to the encoding rules for the
+C++ language.
+.El
+.It "Programming conveniences"
+.Bl -tag -compact
+.It Fn elftc_copyfile
+Copies the contents of a file to another.
+.It Fn elftc_set_timestamp
+Portably set the time stamps on a file.
+.El
+.It "Project Configuration"
+.Bl -tag -compact
+.It Fn elftc_version
+Returns a project-wide identifier string that encodes the source
+revision of the source tree.
+.El
+.El
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr elf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/elftc_bfd_find_target.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,200 @@
+.\" Copyright (c) 2010-2011 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elftc_bfd_find_target.3 3516 2017-02-10 02:33:08Z emaste $
+.\"
+.Dd November 30, 2011
+.Os
+.Dt ELFTC_BFD_FIND_TARGET
+.Sh NAME
+.Nm elftc_bfd_find_target ,
+.Nm elftc_bfd_target_byteorder ,
+.Nm elftc_bfd_target_class ,
+.Nm elftc_bfd_target_flavor ,
+.Nm elftc_bfd_target_machine
+.Nd binary object descriptor handling
+.Sh LIBRARY
+.Lb libelftc
+.Sh SYNOPSIS
+.In libelftc.h
+.Vt struct Elftc_Bfd_Target;
+.Ft "Elftc_Bfd_Target *"
+.Fn elftc_bfd_find_target "const char *target_name"
+.Ft "unsigned int"
+.Fn elftc_bfd_target_class "Elftc_Bfd_Target *target"
+.Ft "unsigned int"
+.Fn elftc_bfd_target_byteorder "Elftc_Bfd_Target *target"
+.Ft Elftc_Bfd_Target_Flavor
+.Fn elftc_bfd_target_flavor "Elftc_Bfd_Target *target"
+.Ft "unsigned int"
+.Fn elftc_bfd_target_machine "Elftc_Bfd_Target *target"
+.Sh DESCRIPTION
+Function
+.Fn elftc_bfd_find_target
+locates a binary object descriptor corresponding to the descriptor
+name in argument
+.Ar "target_name" .
+Binary object descriptors encapsulate properties of an object format
+such as its file representation, ELF class, and byte endianness.
+.Pp
+Known descriptor names and their properties include:
+.Bl -column -offset "XXXX" ".Li elf32-x86-64-freebsd" "Object format" "Byte Order" "Bit Width"
+.It Em Name Ta Em "Object Format" Ta Em "Byte Order" Ta Em "Bit Width"
+.It Li binary Ta Binary Ta - Ta -
+.It Li efi-app-ia32 Ta PE Ta LSB Ta 32
+.It Li efi-app-x86_64 Ta PE Ta LSB Ta 64
+.It Li elf32-avr Ta ELF Ta LSB Ta 32
+.It Li elf32-big Ta ELF Ta MSB Ta 32
+.It Li elf32-bigarm Ta ELF Ta MSB Ta 32
+.It Li elf32-bigmips Ta ELF Ta MSB Ta 32
+.It Li elf32-i386 Ta ELF Ta LSB Ta 32
+.It Li elf32-i386-freebsd Ta ELF Ta LSB Ta 32
+.It Li elf32-ia64-big Ta ELF Ta MSB Ta 32
+.It Li elf32-little Ta ELF Ta LSB Ta 32
+.It Li elf32-littlearm Ta ELF Ta LSB Ta 32
+.It Li elf32-littlemips Ta ELF Ta LSB Ta 32
+.It Li elf32-powerpc Ta ELF Ta MSB Ta 32
+.It Li elf32-powerpc-freebsd Ta ELF Ta MSB Ta 32
+.It Li elf32-powerpcle Ta ELF Ta LSB Ta 32
+.It Li elf32-sh Ta ELF Ta MSB Ta 32
+.It Li elf32-shl Ta ELF Ta LSB Ta 32
+.It Li elf32-sh-nbsd Ta ELF Ta MSB Ta 32
+.It Li elf32-shl-nbsd Ta ELF Ta LSB Ta 32
+.It Li elf32-shbig-linux Ta ELF Ta MSB Ta 32
+.It Li elf32-shl-linux Ta ELF Ta LSB Ta 32
+.It Li elf32-sparc Ta ELF Ta MSB Ta 32
+.It Li elf32-tradbigmips Ta ELF Ta MSB Ta 32
+.It Li elf32-tradlittlemips Ta ELF Ta LSB Ta 32
+.It Li elf64-alpha Ta ELF Ta LSB Ta 64
+.It Li elf64-alpha-freebsd Ta ELF Ta LSB Ta 64
+.It Li elf64-big Ta ELF Ta MSB Ta 64
+.It Li elf64-bigmips Ta ELF Ta MSB Ta 64
+.It Li elf64-ia64-big Ta ELF Ta MSB Ta 64
+.It Li elf64-ia64-little Ta ELF Ta LSB Ta 64
+.It Li elf64-little Ta ELF Ta LSB Ta 64
+.It Li elf64-littleaarch64 Ta ELF Ta LSB Ta 64
+.It Li elf64-littlemips Ta ELF Ta LSB Ta 64
+.It Li elf64-powerpc Ta ELF Ta MSB Ta 64
+.It Li elf64-powerpc-freebsd Ta ELF Ta MSB Ta 64
+.It Li elf64-powerpcle Ta ELF Ta LSB Ta 64
+.It Li elf64-sh64 Ta ELF Ta MSB Ta 64
+.It Li elf64-sh64l Ta ELF Ta LSB Ta 64
+.It Li elf64-sh64-nbsd Ta ELF Ta MSB Ta 64
+.It Li elf64-sh64l-nbsd Ta ELF Ta LSB Ta 64
+.It Li elf64-sh64big-linux Ta ELF Ta MSB Ta 64
+.It Li elf64-sh64-linux Ta ELF Ta LSB Ta 64
+.It Li elf64-sparc Ta ELF Ta MSB Ta 64
+.It Li elf64-sparc-freebsd Ta ELF Ta MSB Ta 64
+.It Li elf64-tradbigmips Ta ELF Ta MSB Ta 64
+.It Li elf64-tradlittlemips Ta ELF Ta LSB Ta 64
+.It Li elf64-x86-64 Ta ELF Ta LSB Ta 64
+.It Li elf64-x86-64-freebsd Ta ELF Ta LSB Ta 64
+.It Li ihex Ta IHEX Ta - Ta -
+.It Li pei-i386 Ta PE Ta LSB Ta 32
+.It Li pei-x86-64 Ta PE Ta LSB Ta 64
+.It Li srec Ta SREC Ta - Ta -
+.It Li symbolsrec Ta SREC Ta - Ta -
+.El
+.Pp
+Function
+.Fn elftc_bfd_target_byteorder
+returns the ELF byte order associated with target descriptor
+.Ar target .
+.Pp
+Function
+.Fn elftc_bfd_target_class
+returns the ELF class associated with target descriptor
+.Ar target .
+.Pp
+Function
+.Fn elftc_bfd_target_flavor
+returns the object format associated with target descriptor
+.Ar target .
+The known object formats are:
+.Bl -tag -offset "XXXX" -width ".Dv ETF_BINARY" -compact
+.It Dv ETF_ELF
+An ELF object.
+.It Dv ETF_BINARY
+Raw binary.
+.It Dv ETF_IHEX
+An object encoded in
+.Tn Intel
+hex format.
+.It Dv ETF_NONE
+An unknown object format.
+.It Dv ETF_SREC
+An object encoded as S-records.
+.El
+.Sh RETURN VALUES
+Function
+.Fn elftc_bfd_find_target
+returns a valid pointer to an opaque binary target descriptor if
+successful, or NULL in case of an error.
+.Pp
+Function
+.Fn elftc_bfd_target_byteorder
+returns the ELF byte order associated with the target descriptor; one of
+.Dv ELFDATA2MSB
+or
+.Dv ELFDATA2LSB .
+.Pp
+Function
+.Fn elftc_bfd_target_class
+returns the ELF class associated with the target descriptor; one of
+.Dv ELFCLASS32
+or
+.Dv ELFCLASS64 .
+.Pp
+Function
+.Fn elftc_bfd_target_machine
+returns the ELF architecture associated with the target descriptor.
+.Pp
+Function
+.Fn elftc_bfd_target_flavor
+returns one of
+.Dv ETF_BINARY ,
+.Dv ETF_ELF ,
+.Dv ETF_IHEX
+or
+.Dv ETF_SREC
+if successful or
+.Dv ETF_NONE
+in case of error.
+.Sh EXAMPLES
+To return descriptor information associated with target name
+.Dq elf64-big
+use:
+.Bd -literal -offset indent
+struct Elftc_Bfd_Target *t;
+
+if ((t = elftc_bfd_find_target("elf64-big")) == NULL)
+	errx(EXIT_FAILURE, "Cannot find target descriptor");
+
+printf("Class: %s\\n", elftc_bfd_target_class(t) == ELFCLASS32 ?
+    "ELFCLASS32" : "ELFCLASS64");
+printf("Byteorder: %s\\n",
+    elftc_bfd_target_byteorder(t) == ELFDATA2LSB ? "LSB" : "MSB");
+printf("Flavor: %d\\n", elftc_bfd_target_flavor(t));
+.Ed
+.Sh SEE ALSO
+.Xr elf 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/elftc_bfdtarget.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,73 @@
+/*-
+ * Copyright (c) 2008,2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <string.h>
+#include <libelftc.h>
+
+#include "_libelftc.h"
+
+ELFTC_VCSID("$Id: elftc_bfdtarget.c 3174 2015-03-27 17:13:41Z emaste $");
+
+Elftc_Bfd_Target *
+elftc_bfd_find_target(const char *tgt_name)
+{
+	Elftc_Bfd_Target *tgt;
+
+	for (tgt = _libelftc_targets; tgt->bt_name; tgt++)
+		if (!strcmp(tgt_name, tgt->bt_name))
+			return (tgt);
+
+	return (NULL);		/* not found */
+}
+
+Elftc_Bfd_Target_Flavor
+elftc_bfd_target_flavor(Elftc_Bfd_Target *tgt)
+{
+
+	return (tgt->bt_type);
+}
+
+unsigned int
+elftc_bfd_target_byteorder(Elftc_Bfd_Target *tgt)
+{
+
+	return (tgt->bt_byteorder);
+}
+
+unsigned int
+elftc_bfd_target_class(Elftc_Bfd_Target *tgt)
+{
+
+	return (tgt->bt_elfclass);
+}
+
+unsigned int
+elftc_bfd_target_machine(Elftc_Bfd_Target *tgt)
+{
+
+	return (tgt->bt_machine);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/elftc_copyfile.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,73 @@
+.\" Copyright (c) 2011 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elftc_copyfile.3 2315 2011-12-11 09:28:55Z jkoshy $
+.\"
+.Dd December 11, 2011
+.Os
+.Dt ELFTC_COPYFILE 3
+.Sh NAME
+.Nm elftc_copyfile
+.Nd convenience function to copy data
+.Sh LIBRARY
+.Lb libelftc
+.Sh SYNOPSIS
+.In libelftc.h
+.Ft in
+.Fn elftc_copyfile "int ifd" "int ofd"
+.Sh DESCRIPTION
+The function
+.Fn elftc_copyfile
+copies the contents of the file referenced by argument
+.Ar ifd
+to the file referenced by argument
+.Ar ofd .
+.Pp
+The argument
+.Ar ifd
+should contain a file descriptor opened for reading, with its file
+offset at the beginning of the file.
+.Pp
+The argument
+.Ar ofd
+should contain a file descriptor opened for writing.
+.Sh RETURN VALUE
+.Rv -std
+.Sh ERRORS
+The function
+.Fn elftc_copyfile
+may fail with any of the errors returned by
+.Xr fstat 2 ,
+.Xr malloc 3 ,
+.Xr mmap 2 ,
+.Xr munmap 2 ,
+.Xr read 2
+or
+.Xr write 2 .
+.Sh SEE ALSO
+.Xr fstat 2 ,
+.Xr malloc 3 ,
+.Xr mmap 2 ,
+.Xr munmap 2 ,
+.Xr read 2 ,
+.Xr write 2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/elftc_copyfile.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,113 @@
+/*-
+ * Copyright (c) 2011, Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "libelftc.h"
+#include "_libelftc.h"
+
+#if	ELFTC_HAVE_MMAP
+#include <sys/mman.h>
+#endif
+
+ELFTC_VCSID("$Id: elftc_copyfile.c 3297 2016-01-09 15:26:34Z jkoshy $");
+
+/*
+ * Copy the contents referenced by 'ifd' to 'ofd'.  Returns 0 on
+ * success and -1 on error.
+ */
+
+int
+elftc_copyfile(int ifd, int ofd)
+{
+	size_t file_size, n;
+	int buf_mmapped;
+	struct stat sb;
+	char *b, *buf;
+	ssize_t nr, nw;
+
+	/* Determine the input file's size. */
+	if (fstat(ifd, &sb) < 0)
+		return (-1);
+
+	/* Skip files without content. */
+	if (sb.st_size == 0)
+		return (0);
+
+	buf = NULL;
+	buf_mmapped = 0;
+	file_size = (size_t) sb.st_size;
+
+#if	ELFTC_HAVE_MMAP
+	/*
+	 * Prefer mmap() if it is available.
+	 */
+	buf = mmap(NULL, file_size, PROT_READ, MAP_SHARED, ifd, (off_t) 0);
+	if (buf != MAP_FAILED)
+		buf_mmapped = 1;
+	else
+		buf = NULL;
+#endif
+
+	/*
+	 * If mmap() is not available, or if the mmap() operation
+	 * failed, allocate a buffer, and read in input data.
+	 */
+	if (buf_mmapped == false) {
+		if ((buf = malloc(file_size)) == NULL)
+			return (-1);
+		b = buf;
+		for (n = file_size; n > 0; n -= (size_t) nr, b += nr) {
+			if ((nr = read(ifd, b, n)) < 0) {
+				free(buf);
+				return (-1);
+			}
+		}
+	}
+
+	/*
+	 * Write data to the output file descriptor.
+	 */
+	for (n = file_size, b = buf; n > 0; n -= (size_t) nw, b += nw)
+		if ((nw = write(ofd, b, n)) <= 0)
+			break;
+
+	/* Release the input buffer. */
+#if	ELFTC_HAVE_MMAP
+	if (buf_mmapped && munmap(buf, file_size) < 0)
+		return (-1);
+#endif
+
+	if (!buf_mmapped)
+		free(buf);
+
+	return (n > 0 ? -1 : 0);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/elftc_demangle.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,116 @@
+.\" Copyright (c) 2009,2011 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elftc_demangle.3 3182 2015-04-10 16:08:10Z emaste $
+.\"
+.Dd August 24, 2011
+.Os
+.Dt ELFTC_DEMANGLE 3
+.Sh NAME
+.Nm elftc_demangle
+.Nd demangle a C++ name
+.Sh LIBRARY
+.Lb libelftc
+.Sh SYNOPSIS
+.In libelftc.h
+.Ft int
+.Fo elftc_demangle
+.Fa "const char *encodedname"
+.Fa "char *buffer"
+.Fa "size_t bufsize"
+.Fa "unsigned int flags"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn elftc_demangle
+decodes a symbol name encoded according to the type encoding rules
+for the C++ language and returns a string denoting an equivalent
+C++ prototype.
+.Pp
+Argument
+.Ar encodedname
+specifies the encoded symbol name.
+Argument
+.Ar buffer
+denotes a programmer-specified area to place the prototype string in.
+Argument
+.Ar bufsize
+specifies the size of the programmer-specified area.
+Argument
+.Ar flags
+specifies the encoding style in use for argument
+.Ar encodedname .
+Supported encoding styles are:
+.Bl -tag -width ".Dv ELFTC_DEM_GNU3"
+.It Dv ELFTC_DEM_ARM
+The encoding style used by compilers adhering to the conventions of the
+C++ Annotated Reference Manual.
+.It Dv ELFTC_DEM_GNU2
+The encoding style by GNU C++ version 2.
+.It Dv ELFTC_DEM_GNU3
+The encoding style by GNU C++ version 3 and later.
+.El
+.Pp
+Argument
+.Ar flags
+may be zero, in which case the function will attempt to guess the
+encoding scheme from the contents of
+.Ar encodedname .
+.Sh RETURN VALUE
+Function
+.Fn elftc_demangle
+returns 0 on success.
+In case of an error it returns -1 and sets the
+.Va errno
+variable.
+.Sh EXAMPLES
+To decode a name that uses an unknown encoding style use:
+.Bd -literal -offset indent
+char buffer[1024];
+const char *funcname;
+
+funcname = ...; /* points to string to be demangled */
+if (elftc_demangle(funcname, buffer, sizeof(buffer), 0) == 0)
+	printf("Demangled name: %\\n", buffer);
+else
+	perror("Cannot demangle %s", funcname);
+.Ed
+.Sh ERRORS
+Function
+.Fn elftc_demangle
+may fail with the following errors:
+.Bl -tag -width ".Bq Er ENAMETOOLONG"
+.It Bq Er EINVAL
+Argument
+.Ar encodedname
+was not a valid encoded name.
+.It Bq Er ENAMETOOLONG
+The output buffer specified by arguments
+.Ar buffer
+and
+.Ar bufsize
+was too small to hold the decoded function prototype.
+.El
+.Sh SEE ALSO
+.Xr elf 3 ,
+.Xr elf_strptr 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/elftc_demangle.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <assert.h>
+#include <errno.h>
+#include <libelftc.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "_libelftc.h"
+
+ELFTC_VCSID("$Id: elftc_demangle.c 3296 2016-01-09 14:17:28Z jkoshy $");
+
+static unsigned int
+is_mangled(const char *s, unsigned int style)
+{
+
+	switch (style) {
+	case ELFTC_DEM_ARM: return (is_cpp_mangled_ARM(s) ? style : 0);
+	case ELFTC_DEM_GNU2: return (is_cpp_mangled_gnu2(s) ? style : 0);
+	case ELFTC_DEM_GNU3: return (is_cpp_mangled_gnu3(s) ? style : 0);
+	}
+
+	/* No style or invalid style spcified, try to guess. */
+	if (is_cpp_mangled_gnu3(s))
+		return (ELFTC_DEM_GNU3);
+	if (is_cpp_mangled_gnu2(s))
+		return (ELFTC_DEM_GNU2);
+	if (is_cpp_mangled_ARM(s))
+		return (ELFTC_DEM_ARM);
+
+	/* Cannot be demangled. */
+	return (0);
+}
+
+static char *
+demangle(const char *s, unsigned int style, unsigned int rc)
+{
+
+	(void) rc;			/* XXX */
+	switch (style) {
+	case ELFTC_DEM_ARM: return (cpp_demangle_ARM(s));
+	case ELFTC_DEM_GNU2: return (cpp_demangle_gnu2(s));
+	case ELFTC_DEM_GNU3: return (cpp_demangle_gnu3(s));
+	default:
+		assert(0);
+		return (NULL);
+	}
+}
+
+int
+elftc_demangle(const char *mangledname, char *buffer, size_t bufsize,
+    unsigned int flags)
+{
+	unsigned int style, rc;
+	char *rlt;
+
+	style = flags & 0xFFFF;
+	rc = flags >> 16;
+
+	if (mangledname == NULL ||
+	    ((style = is_mangled(mangledname, style)) == 0)) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	if ((rlt = demangle(mangledname, style, rc)) == NULL) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	if (buffer == NULL || bufsize < strlen(rlt) + 1) {
+		free(rlt);
+		errno = ENAMETOOLONG;
+		return (-1);
+	}
+
+	strncpy(buffer, rlt, bufsize);
+	buffer[bufsize - 1] = '\0';
+	free(rlt);
+
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/elftc_reloc_type_str.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,72 @@
+.\" Copyright (c) 2016 The FreeBSD Foundation.  All rights reserved.
+.\"
+.\" This documentation was written by Ed Maste under sponsorship of
+.\" the FreeBSD Foundation.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by the author and contributors ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  In no event shall the author or contributors be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id$
+.\"
+.Dd February 19, 2016
+.Os
+.Dt ELFTC_RELOC_TYPE_STR 3
+.Sh NAME
+.Nm elftc_reloc_type_str
+.Nd return the type name for an ELF relocation
+.Sh LIBRARY
+.Lb libelftc
+.Sh SYNOPSIS
+.In libelftc.h
+.Ft const char *
+.Fo elftc_reloc_type_str
+.Fa "unsigned int mach"
+.Fa "unsigned int type"
+.Fc
+.Sh DESCRIPTION
+Function
+.Fn elftc_reloc_type_str
+returns the name for specified relocation type.
+.Pp
+Argument
+.Ar mach
+specifies the machine (architecture) type.
+Argument
+.Ar type
+specifies the relocation value.
+.Sh RETURN VALUE
+Function
+.Fn elftc_program_version
+returns a pointer to a string constant, or to an internal character buffer
+if the relocation type is unknown.
+.Sh EXAMPLES
+To print ARM relocation type 7, use:
+.Bd -literal -offset indent
+#include <sys/types.h>
+#include <libelftc.h>
+#include <stdio.h>
+
+(void) printf("%s\en", elftc_reloc_type_str(EM_ARM, 7));
+.Ed
+.Sh ERRORS
+Function
+.Fn elftc_reloc_type_str
+always succeeds.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/elftc_reloc_type_str.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,834 @@
+/*-
+ * Copyright (c) 2009-2015 Kai Wang
+ * Copyright (c) 2016 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Portions of this software were developed by Ed Maste under sponsorship
+ * of the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <libelftc.h>
+#include <stdio.h>
+
+const char *
+elftc_reloc_type_str(unsigned int mach, unsigned int type)
+{
+	static char s_type[32];
+
+	switch(mach) {
+	case EM_386:
+	case EM_IAMCU:
+		switch(type) {
+		case 0: return "R_386_NONE";
+		case 1: return "R_386_32";
+		case 2: return "R_386_PC32";
+		case 3: return "R_386_GOT32";
+		case 4: return "R_386_PLT32";
+		case 5: return "R_386_COPY";
+		case 6: return "R_386_GLOB_DAT";
+		case 7: return "R_386_JUMP_SLOT";
+		case 8: return "R_386_RELATIVE";
+		case 9: return "R_386_GOTOFF";
+		case 10: return "R_386_GOTPC";
+		case 11: return "R_386_32PLT"; /* Not in psabi */
+		case 14: return "R_386_TLS_TPOFF";
+		case 15: return "R_386_TLS_IE";
+		case 16: return "R_386_TLS_GOTIE";
+		case 17: return "R_386_TLS_LE";
+		case 18: return "R_386_TLS_GD";
+		case 19: return "R_386_TLS_LDM";
+		case 20: return "R_386_16";
+		case 21: return "R_386_PC16";
+		case 22: return "R_386_8";
+		case 23: return "R_386_PC8";
+		case 24: return "R_386_TLS_GD_32";
+		case 25: return "R_386_TLS_GD_PUSH";
+		case 26: return "R_386_TLS_GD_CALL";
+		case 27: return "R_386_TLS_GD_POP";
+		case 28: return "R_386_TLS_LDM_32";
+		case 29: return "R_386_TLS_LDM_PUSH";
+		case 30: return "R_386_TLS_LDM_CALL";
+		case 31: return "R_386_TLS_LDM_POP";
+		case 32: return "R_386_TLS_LDO_32";
+		case 33: return "R_386_TLS_IE_32";
+		case 34: return "R_386_TLS_LE_32";
+		case 35: return "R_386_TLS_DTPMOD32";
+		case 36: return "R_386_TLS_DTPOFF32";
+		case 37: return "R_386_TLS_TPOFF32";
+		case 38: return "R_386_SIZE32";
+		case 39: return "R_386_TLS_GOTDESC";
+		case 40: return "R_386_TLS_DESC_CALL";
+		case 41: return "R_386_TLS_DESC";
+		case 42: return "R_386_IRELATIVE";
+		case 43: return "R_386_GOT32X";
+		}
+		break;
+	case EM_AARCH64:
+		switch(type) {
+		case 0: return "R_AARCH64_NONE";
+		case 257: return "R_AARCH64_ABS64";
+		case 258: return "R_AARCH64_ABS32";
+		case 259: return "R_AARCH64_ABS16";
+		case 260: return "R_AARCH64_PREL64";
+		case 261: return "R_AARCH64_PREL32";
+		case 262: return "R_AARCH64_PREL16";
+		case 263: return "R_AARCH64_MOVW_UABS_G0";
+		case 264: return "R_AARCH64_MOVW_UABS_G0_NC";
+		case 265: return "R_AARCH64_MOVW_UABS_G1";
+		case 266: return "R_AARCH64_MOVW_UABS_G1_NC";
+		case 267: return "R_AARCH64_MOVW_UABS_G2";
+		case 268: return "R_AARCH64_MOVW_UABS_G2_NC";
+		case 269: return "R_AARCH64_MOVW_UABS_G3";
+		case 270: return "R_AARCH64_MOVW_SABS_G0";
+		case 271: return "R_AARCH64_MOVW_SABS_G1";
+		case 272: return "R_AARCH64_MOVW_SABS_G2";
+		case 273: return "R_AARCH64_LD_PREL_LO19";
+		case 274: return "R_AARCH64_ADR_PREL_LO21";
+		case 275: return "R_AARCH64_ADR_PREL_PG_HI21";
+		case 276: return "R_AARCH64_ADR_PREL_PG_HI21_NC";
+		case 277: return "R_AARCH64_ADD_ABS_LO12_NC";
+		case 278: return "R_AARCH64_LDST8_ABS_LO12_NC";
+		case 279: return "R_AARCH64_TSTBR14";
+		case 280: return "R_AARCH64_CONDBR19";
+		case 282: return "R_AARCH64_JUMP26";
+		case 283: return "R_AARCH64_CALL26";
+		case 284: return "R_AARCH64_LDST16_ABS_LO12_NC";
+		case 285: return "R_AARCH64_LDST32_ABS_LO12_NC";
+		case 286: return "R_AARCH64_LDST64_ABS_LO12_NC";
+		case 287: return "R_AARCH64_MOVW_PREL_G0";
+		case 288: return "R_AARCH64_MOVW_PREL_G0_NC";
+		case 289: return "R_AARCH64_MOVW_PREL_G1";
+		case 290: return "R_AARCH64_MOVW_PREL_G1_NC";
+		case 291: return "R_AARCH64_MOVW_PREL_G2";
+		case 292: return "R_AARCH64_MOVW_PREL_G2_NC";
+		case 293: return "R_AARCH64_MOVW_PREL_G3";
+		case 299: return "R_AARCH64_LDST128_ABS_LO12_NC";
+		case 300: return "R_AARCH64_MOVW_GOTOFF_G0";
+		case 301: return "R_AARCH64_MOVW_GOTOFF_G0_NC";
+		case 302: return "R_AARCH64_MOVW_GOTOFF_G1";
+		case 303: return "R_AARCH64_MOVW_GOTOFF_G1_NC";
+		case 304: return "R_AARCH64_MOVW_GOTOFF_G2";
+		case 305: return "R_AARCH64_MOVW_GOTOFF_G2_NC";
+		case 306: return "R_AARCH64_MOVW_GOTOFF_G3";
+		case 307: return "R_AARCH64_GOTREL64";
+		case 308: return "R_AARCH64_GOTREL32";
+		case 309: return "R_AARCH64_GOT_LD_PREL19";
+		case 310: return "R_AARCH64_LD64_GOTOFF_LO15";
+		case 311: return "R_AARCH64_ADR_GOT_PAGE";
+		case 312: return "R_AARCH64_LD64_GOT_LO12_NC";
+		case 313: return "R_AARCH64_LD64_GOTPAGE_LO15";
+		case 560: return "R_AARCH64_TLSDESC_LD_PREL19";
+		case 561: return "R_AARCH64_TLSDESC_ADR_PREL21";
+		case 562: return "R_AARCH64_TLSDESC_ADR_PAGE21";
+		case 563: return "R_AARCH64_TLSDESC_LD64_LO12";
+		case 564: return "R_AARCH64_TLSDESC_ADD_LO12";
+		case 565: return "R_AARCH64_TLSDESC_OFF_G1";
+		case 566: return "R_AARCH64_TLSDESC_OFF_G0_NC";
+		case 567: return "R_AARCH64_TLSDESC_LDR";
+		case 568: return "R_AARCH64_TLSDESC_ADD";
+		case 569: return "R_AARCH64_TLSDESC_CALL";
+		case 1024: return "R_AARCH64_COPY";
+		case 1025: return "R_AARCH64_GLOB_DAT";
+		case 1026: return "R_AARCH64_JUMP_SLOT";
+		case 1027: return "R_AARCH64_RELATIVE";
+		case 1028: return "R_AARCH64_TLS_DTPREL64";
+		case 1029: return "R_AARCH64_TLS_DTPMOD64";
+		case 1030: return "R_AARCH64_TLS_TPREL64";
+		case 1031: return "R_AARCH64_TLSDESC";
+		case 1032: return "R_AARCH64_IRELATIVE";
+		}
+		break;
+	case EM_ARM:
+		switch(type) {
+		case 0: return "R_ARM_NONE";
+		case 1: return "R_ARM_PC24"; /* Deprecated */
+		case 2: return "R_ARM_ABS32";
+		case 3: return "R_ARM_REL32";
+		case 4: return "R_ARM_LDR_PC_G0"; /* Also R_ARM_PC13 */
+		case 5: return "R_ARM_ABS16";
+		case 6: return "R_ARM_ABS12";
+		case 7: return "R_ARM_THM_ABS5";
+		case 8: return "R_ARM_ABS8";
+		case 9: return "R_ARM_SBREL32";
+		case 10: return "R_ARM_THM_CALL"; /* Also R_ARM_THM_PC22 */
+		case 11: return "R_ARM_THM_PC8";
+		case 12: return "R_ARM_BREL_ADJ"; /* Also R_ARM_AMP_VCALL9 */
+		case 13: return "R_ARM_TLS_DESC"; /* Also R_ARM_SWI24 */
+		case 14: return "R_ARM_THM_SWI8"; /* Obsolete */
+		case 15: return "R_ARM_XPC25"; /* Obsolete */
+		case 16: return "R_ARM_THM_XPC22"; /* Obsolete */
+		case 17: return "R_ARM_TLS_DTPMOD32";
+		case 18: return "R_ARM_TLS_DTPOFF32";
+		case 19: return "R_ARM_TLS_TPOFF32";
+		case 20: return "R_ARM_COPY";
+		case 21: return "R_ARM_GLOB_DAT";
+		case 22: return "R_ARM_JUMP_SLOT";
+		case 23: return "R_ARM_RELATIVE";
+		case 24: return "R_ARM_GOTOFF32"; /* Also R_ARM_GOTOFF */
+		case 25: return "R_ARM_BASE_PREL"; /* GNU R_ARM_GOTPC */
+		case 26: return "R_ARM_GOT_BREL"; /* GNU R_ARM_GOT32 */
+		case 27: return "R_ARM_PLT32"; /* Deprecated */
+		case 28: return "R_ARM_CALL";
+		case 29: return "R_ARM_JUMP24";
+		case 30: return "R_ARM_THM_JUMP24";
+		case 31: return "R_ARM_BASE_ABS";
+		case 32: return "R_ARM_ALU_PCREL_7_0"; /* Obsolete */
+		case 33: return "R_ARM_ALU_PCREL_15_8"; /* Obsolete */
+		case 34: return "R_ARM_ALU_PCREL_23_15"; /* Obsolete */
+		case 35: return "R_ARM_LDR_SBREL_11_0_NC"; /* Deprecated */
+		case 36: return "R_ARM_ALU_SBREL_19_12_NC"; /* Deprecated */
+		case 37: return "R_ARM_ALU_SBREL_27_20_CK"; /* Deprecated */
+		case 38: return "R_ARM_TARGET1";
+		case 39: return "R_ARM_SBREL31"; /* Deprecated. */
+		case 40: return "R_ARM_V4BX";
+		case 41: return "R_ARM_TARGET2";
+		case 42: return "R_ARM_PREL31";
+		case 43: return "R_ARM_MOVW_ABS_NC";
+		case 44: return "R_ARM_MOVT_ABS";
+		case 45: return "R_ARM_MOVW_PREL_NC";
+		case 46: return "R_ARM_MOVT_PREL";
+		case 47: return "R_ARM_THM_MOVW_ABS_NC";
+		case 48: return "R_ARM_THM_MOVT_ABS";
+		case 49: return "R_ARM_THM_MOVW_PREL_NC";
+		case 50: return "R_ARM_THM_MOVT_PREL";
+		case 51: return "R_ARM_THM_JUMP19";
+		case 52: return "R_ARM_THM_JUMP6";
+		case 53: return "R_ARM_THM_ALU_PREL_11_0";
+		case 54: return "R_ARM_THM_PC12";
+		case 55: return "R_ARM_ABS32_NOI";
+		case 56: return "R_ARM_REL32_NOI";
+		case 57: return "R_ARM_ALU_PC_G0_NC";
+		case 58: return "R_ARM_ALU_PC_G0";
+		case 59: return "R_ARM_ALU_PC_G1_NC";
+		case 60: return "R_ARM_ALU_PC_G1";
+		case 61: return "R_ARM_ALU_PC_G2";
+		case 62: return "R_ARM_LDR_PC_G1";
+		case 63: return "R_ARM_LDR_PC_G2";
+		case 64: return "R_ARM_LDRS_PC_G0";
+		case 65: return "R_ARM_LDRS_PC_G1";
+		case 66: return "R_ARM_LDRS_PC_G2";
+		case 67: return "R_ARM_LDC_PC_G0";
+		case 68: return "R_ARM_LDC_PC_G1";
+		case 69: return "R_ARM_LDC_PC_G2";
+		case 70: return "R_ARM_ALU_SB_G0_NC";
+		case 71: return "R_ARM_ALU_SB_G0";
+		case 72: return "R_ARM_ALU_SB_G1_NC";
+		case 73: return "R_ARM_ALU_SB_G1";
+		case 74: return "R_ARM_ALU_SB_G2";
+		case 75: return "R_ARM_LDR_SB_G0";
+		case 76: return "R_ARM_LDR_SB_G1";
+		case 77: return "R_ARM_LDR_SB_G2";
+		case 78: return "R_ARM_LDRS_SB_G0";
+		case 79: return "R_ARM_LDRS_SB_G1";
+		case 80: return "R_ARM_LDRS_SB_G2";
+		case 81: return "R_ARM_LDC_SB_G0";
+		case 82: return "R_ARM_LDC_SB_G1";
+		case 83: return "R_ARM_LDC_SB_G2";
+		case 84: return "R_ARM_MOVW_BREL_NC";
+		case 85: return "R_ARM_MOVT_BREL";
+		case 86: return "R_ARM_MOVW_BREL";
+		case 87: return "R_ARM_THM_MOVW_BREL_NC";
+		case 88: return "R_ARM_THM_MOVT_BREL";
+		case 89: return "R_ARM_THM_MOVW_BREL";
+		case 90: return "R_ARM_TLS_GOTDESC";
+		case 91: return "R_ARM_TLS_CALL";
+		case 92: return "R_ARM_TLS_DESCSEQ";
+		case 93: return "R_ARM_THM_TLS_CALL";
+		case 94: return "R_ARM_PLT32_ABS";
+		case 95: return "R_ARM_GOT_ABS";
+		case 96: return "R_ARM_GOT_PREL";
+		case 97: return "R_ARM_GOT_BREL12";
+		case 98: return "R_ARM_GOTOFF12";
+		case 99: return "R_ARM_GOTRELAX";
+		case 100: return "R_ARM_GNU_VTENTRY";
+		case 101: return "R_ARM_GNU_VTINHERIT";
+		case 102: return "R_ARM_THM_JUMP11"; /* Also R_ARM_THM_PC11 */
+		case 103: return "R_ARM_THM_JUMP8"; /* Also R_ARM_THM_PC9 */
+		case 104: return "R_ARM_TLS_GD32";
+		case 105: return "R_ARM_TLS_LDM32";
+		case 106: return "R_ARM_TLS_LDO32";
+		case 107: return "R_ARM_TLS_IE32";
+		case 108: return "R_ARM_TLS_LE32";
+		case 109: return "R_ARM_TLS_LDO12";
+		case 110: return "R_ARM_TLS_LE12";
+		case 111: return "R_ARM_TLS_IE12GP";
+		/* 112-127 R_ARM_PRIVATE_<n> */
+		case 128: return "R_ARM_ME_TOO"; /* Obsolete */
+		case 129: return "R_ARM_THM_TLS_DESCSEQ16";
+		case 130: return "R_ARM_THM_TLS_DESCSEQ32";
+		case 131: return "R_ARM_THM_GOT_BREL12";
+		case 132: return "R_ARM_THM_ALU_ABS_G0_NC";
+		case 133: return "R_ARM_THM_ALU_ABS_G1_NC";
+		case 134: return "R_ARM_THM_ALU_ABS_G2_NC";
+		case 135: return "R_ARM_THM_ALU_ABS_G3";
+		/* 136-159 Reserved for future allocation. */
+		case 160: return "R_ARM_IRELATIVE";
+		/* 161-255 Reserved for future allocation. */
+		case 249: return "R_ARM_RXPC25";
+		case 250: return "R_ARM_RSBREL32";
+		case 251: return "R_ARM_THM_RPC22";
+		case 252: return "R_ARM_RREL32";
+		case 253: return "R_ARM_RABS32";
+		case 254: return "R_ARM_RPC24";
+		case 255: return "R_ARM_RBASE";
+		}
+		break;
+	case EM_IA_64:
+		switch(type) {
+		case 0: return "R_IA_64_NONE";
+		case 33: return "R_IA_64_IMM14";
+		case 34: return "R_IA_64_IMM22";
+		case 35: return "R_IA_64_IMM64";
+		case 36: return "R_IA_64_DIR32MSB";
+		case 37: return "R_IA_64_DIR32LSB";
+		case 38: return "R_IA_64_DIR64MSB";
+		case 39: return "R_IA_64_DIR64LSB";
+		case 42: return "R_IA_64_GPREL22";
+		case 43: return "R_IA_64_GPREL64I";
+		case 44: return "R_IA_64_GPREL32MSB";
+		case 45: return "R_IA_64_GPREL32LSB";
+		case 46: return "R_IA_64_GPREL64MSB";
+		case 47: return "R_IA_64_GPREL64LSB";
+		case 50: return "R_IA_64_LTOFF22";
+		case 51: return "R_IA_64_LTOFF64I";
+		case 58: return "R_IA_64_PLTOFF22";
+		case 59: return "R_IA_64_PLTOFF64I";
+		case 62: return "R_IA_64_PLTOFF64MSB";
+		case 63: return "R_IA_64_PLTOFF64LSB";
+		case 67: return "R_IA_64_FPTR64I";
+		case 68: return "R_IA_64_FPTR32MSB";
+		case 69: return "R_IA_64_FPTR32LSB";
+		case 70: return "R_IA_64_FPTR64MSB";
+		case 71: return "R_IA_64_FPTR64LSB";
+		case 72: return "R_IA_64_PCREL60B";
+		case 73: return "R_IA_64_PCREL21B";
+		case 74: return "R_IA_64_PCREL21M";
+		case 75: return "R_IA_64_PCREL21F";
+		case 76: return "R_IA_64_PCREL32MSB";
+		case 77: return "R_IA_64_PCREL32LSB";
+		case 78: return "R_IA_64_PCREL64MSB";
+		case 79: return "R_IA_64_PCREL64LSB";
+		case 82: return "R_IA_64_LTOFF_FPTR22";
+		case 83: return "R_IA_64_LTOFF_FPTR64I";
+		case 84: return "R_IA_64_LTOFF_FPTR32MSB";
+		case 85: return "R_IA_64_LTOFF_FPTR32LSB";
+		case 86: return "R_IA_64_LTOFF_FPTR64MSB";
+		case 87: return "R_IA_64_LTOFF_FPTR64LSB";
+		case 92: return "R_IA_64_SEGREL32MSB";
+		case 93: return "R_IA_64_SEGREL32LSB";
+		case 94: return "R_IA_64_SEGREL64MSB";
+		case 95: return "R_IA_64_SEGREL64LSB";
+		case 100: return "R_IA_64_SECREL32MSB";
+		case 101: return "R_IA_64_SECREL32LSB";
+		case 102: return "R_IA_64_SECREL64MSB";
+		case 103: return "R_IA_64_SECREL64LSB";
+		case 108: return "R_IA_64_REL32MSB";
+		case 109: return "R_IA_64_REL32LSB";
+		case 110: return "R_IA_64_REL64MSB";
+		case 111: return "R_IA_64_REL64LSB";
+		case 116: return "R_IA_64_LTV32MSB";
+		case 117: return "R_IA_64_LTV32LSB";
+		case 118: return "R_IA_64_LTV64MSB";
+		case 119: return "R_IA_64_LTV64LSB";
+		case 121: return "R_IA_64_PCREL21BI";
+		case 122: return "R_IA_64_PCREL22";
+		case 123: return "R_IA_64_PCREL64I";
+		case 128: return "R_IA_64_IPLTMSB";
+		case 129: return "R_IA_64_IPLTLSB";
+		case 133: return "R_IA_64_SUB";
+		case 134: return "R_IA_64_LTOFF22X";
+		case 135: return "R_IA_64_LDXMOV";
+		case 145: return "R_IA_64_TPREL14";
+		case 146: return "R_IA_64_TPREL22";
+		case 147: return "R_IA_64_TPREL64I";
+		case 150: return "R_IA_64_TPREL64MSB";
+		case 151: return "R_IA_64_TPREL64LSB";
+		case 154: return "R_IA_64_LTOFF_TPREL22";
+		case 166: return "R_IA_64_DTPMOD64MSB";
+		case 167: return "R_IA_64_DTPMOD64LSB";
+		case 170: return "R_IA_64_LTOFF_DTPMOD22";
+		case 177: return "R_IA_64_DTPREL14";
+		case 178: return "R_IA_64_DTPREL22";
+		case 179: return "R_IA_64_DTPREL64I";
+		case 180: return "R_IA_64_DTPREL32MSB";
+		case 181: return "R_IA_64_DTPREL32LSB";
+		case 182: return "R_IA_64_DTPREL64MSB";
+		case 183: return "R_IA_64_DTPREL64LSB";
+		case 186: return "R_IA_64_LTOFF_DTPREL22";
+		}
+		break;
+	case EM_MIPS:
+		switch(type) {
+		case 0: return "R_MIPS_NONE";
+		case 1: return "R_MIPS_16";
+		case 2: return "R_MIPS_32";
+		case 3: return "R_MIPS_REL32";
+		case 4: return "R_MIPS_26";
+		case 5: return "R_MIPS_HI16";
+		case 6: return "R_MIPS_LO16";
+		case 7: return "R_MIPS_GPREL16";
+		case 8: return "R_MIPS_LITERAL";
+		case 9: return "R_MIPS_GOT16";
+		case 10: return "R_MIPS_PC16";
+		case 11: return "R_MIPS_CALL16";
+		case 12: return "R_MIPS_GPREL32";
+		case 16: return "R_MIPS_SHIFT5";
+		case 17: return "R_MIPS_SHIFT6";
+		case 18: return "R_MIPS_64";
+		case 19: return "R_MIPS_GOT_DISP";
+		case 20: return "R_MIPS_GOT_PAGE";
+		case 21: return "R_MIPS_GOT_OFST";
+		case 22: return "R_MIPS_GOT_HI16";
+		case 23: return "R_MIPS_GOT_LO16";
+		case 24: return "R_MIPS_SUB";
+		case 28: return "R_MIPS_HIGHER";
+		case 29: return "R_MIPS_HIGHEST";
+		case 30: return "R_MIPS_CALLHI16";
+		case 31: return "R_MIPS_CALLLO16";
+		case 37: return "R_MIPS_JALR";
+		case 38: return "R_MIPS_TLS_DTPMOD32";
+		case 39: return "R_MIPS_TLS_DTPREL32";
+		case 40: return "R_MIPS_TLS_DTPMOD64";
+		case 41: return "R_MIPS_TLS_DTPREL64";
+		case 42: return "R_MIPS_TLS_GD";
+		case 43: return "R_MIPS_TLS_LDM";
+		case 44: return "R_MIPS_TLS_DTPREL_HI16";
+		case 45: return "R_MIPS_TLS_DTPREL_LO16";
+		case 46: return "R_MIPS_TLS_GOTTPREL";
+		case 47: return "R_MIPS_TLS_TPREL32";
+		case 48: return "R_MIPS_TLS_TPREL64";
+		case 49: return "R_MIPS_TLS_TPREL_HI16";
+		case 50: return "R_MIPS_TLS_TPREL_LO16";
+		}
+		break;
+	case EM_PPC:
+		switch(type) {
+		case 0: return "R_PPC_NONE";
+		case 1: return "R_PPC_ADDR32";
+		case 2: return "R_PPC_ADDR24";
+		case 3: return "R_PPC_ADDR16";
+		case 4: return "R_PPC_ADDR16_LO";
+		case 5: return "R_PPC_ADDR16_HI";
+		case 6: return "R_PPC_ADDR16_HA";
+		case 7: return "R_PPC_ADDR14";
+		case 8: return "R_PPC_ADDR14_BRTAKEN";
+		case 9: return "R_PPC_ADDR14_BRNTAKEN";
+		case 10: return "R_PPC_REL24";
+		case 11: return "R_PPC_REL14";
+		case 12: return "R_PPC_REL14_BRTAKEN";
+		case 13: return "R_PPC_REL14_BRNTAKEN";
+		case 14: return "R_PPC_GOT16";
+		case 15: return "R_PPC_GOT16_LO";
+		case 16: return "R_PPC_GOT16_HI";
+		case 17: return "R_PPC_GOT16_HA";
+		case 18: return "R_PPC_PLTREL24";
+		case 19: return "R_PPC_COPY";
+		case 20: return "R_PPC_GLOB_DAT";
+		case 21: return "R_PPC_JMP_SLOT";
+		case 22: return "R_PPC_RELATIVE";
+		case 23: return "R_PPC_LOCAL24PC";
+		case 24: return "R_PPC_UADDR32";
+		case 25: return "R_PPC_UADDR16";
+		case 26: return "R_PPC_REL32";
+		case 27: return "R_PPC_PLT32";
+		case 28: return "R_PPC_PLTREL32";
+		case 29: return "R_PPC_PLT16_LO";
+		case 30: return "R_PPC_PLT16_HI";
+		case 31: return "R_PPC_PLT16_HA";
+		case 32: return "R_PPC_SDAREL16";
+		case 33: return "R_PPC_SECTOFF";
+		case 34: return "R_PPC_SECTOFF_LO";
+		case 35: return "R_PPC_SECTOFF_HI";
+		case 36: return "R_PPC_SECTOFF_HA";
+		case 67: return "R_PPC_TLS";
+		case 68: return "R_PPC_DTPMOD32";
+		case 69: return "R_PPC_TPREL16";
+		case 70: return "R_PPC_TPREL16_LO";
+		case 71: return "R_PPC_TPREL16_HI";
+		case 72: return "R_PPC_TPREL16_HA";
+		case 73: return "R_PPC_TPREL32";
+		case 74: return "R_PPC_DTPREL16";
+		case 75: return "R_PPC_DTPREL16_LO";
+		case 76: return "R_PPC_DTPREL16_HI";
+		case 77: return "R_PPC_DTPREL16_HA";
+		case 78: return "R_PPC_DTPREL32";
+		case 79: return "R_PPC_GOT_TLSGD16";
+		case 80: return "R_PPC_GOT_TLSGD16_LO";
+		case 81: return "R_PPC_GOT_TLSGD16_HI";
+		case 82: return "R_PPC_GOT_TLSGD16_HA";
+		case 83: return "R_PPC_GOT_TLSLD16";
+		case 84: return "R_PPC_GOT_TLSLD16_LO";
+		case 85: return "R_PPC_GOT_TLSLD16_HI";
+		case 86: return "R_PPC_GOT_TLSLD16_HA";
+		case 87: return "R_PPC_GOT_TPREL16";
+		case 88: return "R_PPC_GOT_TPREL16_LO";
+		case 89: return "R_PPC_GOT_TPREL16_HI";
+		case 90: return "R_PPC_GOT_TPREL16_HA";
+		case 101: return "R_PPC_EMB_NADDR32";
+		case 102: return "R_PPC_EMB_NADDR16";
+		case 103: return "R_PPC_EMB_NADDR16_LO";
+		case 104: return "R_PPC_EMB_NADDR16_HI";
+		case 105: return "R_PPC_EMB_NADDR16_HA";
+		case 106: return "R_PPC_EMB_SDAI16";
+		case 107: return "R_PPC_EMB_SDA2I16";
+		case 108: return "R_PPC_EMB_SDA2REL";
+		case 109: return "R_PPC_EMB_SDA21";
+		case 110: return "R_PPC_EMB_MRKREF";
+		case 111: return "R_PPC_EMB_RELSEC16";
+		case 112: return "R_PPC_EMB_RELST_LO";
+		case 113: return "R_PPC_EMB_RELST_HI";
+		case 114: return "R_PPC_EMB_RELST_HA";
+		case 115: return "R_PPC_EMB_BIT_FLD";
+		case 116: return "R_PPC_EMB_RELSDA";
+		}
+		break;
+	case EM_PPC64:
+		switch(type) {
+		case 0: return "R_PPC64_NONE";
+		case 1: return "R_PPC64_ADDR32";
+		case 2: return "R_PPC64_ADDR24";
+		case 3: return "R_PPC64_ADDR16";
+		case 4: return "R_PPC64_ADDR16_LO";
+		case 5: return "R_PPC64_ADDR16_HI";
+		case 6: return "R_PPC64_ADDR16_HA";
+		case 7: return "R_PPC64_ADDR14";
+		case 8: return "R_PPC64_ADDR14_BRTAKEN";
+		case 9: return "R_PPC64_ADDR14_BRNTAKEN";
+		case 10: return "R_PPC64_REL24";
+		case 11: return "R_PPC64_REL14";
+		case 12: return "R_PPC64_REL14_BRTAKEN";
+		case 13: return "R_PPC64_REL14_BRNTAKEN";
+		case 14: return "R_PPC64_GOT16";
+		case 15: return "R_PPC64_GOT16_LO";
+		case 16: return "R_PPC64_GOT16_HI";
+		case 17: return "R_PPC64_GOT16_HA";
+		case 19: return "R_PPC64_COPY";
+		case 20: return "R_PPC64_GLOB_DAT";
+		case 21: return "R_PPC64_JMP_SLOT";
+		case 22: return "R_PPC64_RELATIVE";
+		case 24: return "R_PPC64_UADDR32";
+		case 25: return "R_PPC64_UADDR16";
+		case 26: return "R_PPC64_REL32";
+		case 27: return "R_PPC64_PLT32";
+		case 28: return "R_PPC64_PLTREL32";
+		case 29: return "R_PPC64_PLT16_LO";
+		case 30: return "R_PPC64_PLT16_HI";
+		case 31: return "R_PPC64_PLT16_HA";
+		case 33: return "R_PPC64_SECTOFF";
+		case 34: return "R_PPC64_SECTOFF_LO";
+		case 35: return "R_PPC64_SECTOFF_HI";
+		case 36: return "R_PPC64_SECTOFF_HA";
+		case 37: return "R_PPC64_ADDR30";
+		case 38: return "R_PPC64_ADDR64";
+		case 39: return "R_PPC64_ADDR16_HIGHER";
+		case 40: return "R_PPC64_ADDR16_HIGHERA";
+		case 41: return "R_PPC64_ADDR16_HIGHEST";
+		case 42: return "R_PPC64_ADDR16_HIGHESTA";
+		case 43: return "R_PPC64_UADDR64";
+		case 44: return "R_PPC64_REL64";
+		case 45: return "R_PPC64_PLT64";
+		case 46: return "R_PPC64_PLTREL64";
+		case 47: return "R_PPC64_TOC16";
+		case 48: return "R_PPC64_TOC16_LO";
+		case 49: return "R_PPC64_TOC16_HI";
+		case 50: return "R_PPC64_TOC16_HA";
+		case 51: return "R_PPC64_TOC";
+		case 52: return "R_PPC64_PLTGOT16";
+		case 53: return "R_PPC64_PLTGOT16_LO";
+		case 54: return "R_PPC64_PLTGOT16_HI";
+		case 55: return "R_PPC64_PLTGOT16_HA";
+		case 56: return "R_PPC64_ADDR16_DS";
+		case 57: return "R_PPC64_ADDR16_LO_DS";
+		case 58: return "R_PPC64_GOT16_DS";
+		case 59: return "R_PPC64_GOT16_LO_DS";
+		case 60: return "R_PPC64_PLT16_LO_DS";
+		case 61: return "R_PPC64_SECTOFF_DS";
+		case 62: return "R_PPC64_SECTOFF_LO_DS";
+		case 63: return "R_PPC64_TOC16_DS";
+		case 64: return "R_PPC64_TOC16_LO_DS";
+		case 65: return "R_PPC64_PLTGOT16_DS";
+		case 66: return "R_PPC64_PLTGOT16_LO_DS";
+		case 67: return "R_PPC64_TLS";
+		case 68: return "R_PPC64_DTPMOD64";
+		case 69: return "R_PPC64_TPREL16";
+		case 70: return "R_PPC64_TPREL16_LO";
+		case 71: return "R_PPC64_TPREL16_HI";
+		case 72: return "R_PPC64_TPREL16_HA";
+		case 73: return "R_PPC64_TPREL64";
+		case 74: return "R_PPC64_DTPREL16";
+		case 75: return "R_PPC64_DTPREL16_LO";
+		case 76: return "R_PPC64_DTPREL16_HI";
+		case 77: return "R_PPC64_DTPREL16_HA";
+		case 78: return "R_PPC64_DTPREL64";
+		case 79: return "R_PPC64_GOT_TLSGD16";
+		case 80: return "R_PPC64_GOT_TLSGD16_LO";
+		case 81: return "R_PPC64_GOT_TLSGD16_HI";
+		case 82: return "R_PPC64_GOT_TLSGD16_HA";
+		case 83: return "R_PPC64_GOT_TLSLD16";
+		case 84: return "R_PPC64_GOT_TLSLD16_LO";
+		case 85: return "R_PPC64_GOT_TLSLD16_HI";
+		case 86: return "R_PPC64_GOT_TLSLD16_HA";
+		case 87: return "R_PPC64_GOT_TPREL16_DS";
+		case 88: return "R_PPC64_GOT_TPREL16_LO_DS";
+		case 89: return "R_PPC64_GOT_TPREL16_HI";
+		case 90: return "R_PPC64_GOT_TPREL16_HA";
+		case 91: return "R_PPC64_GOT_DTPREL16_DS";
+		case 92: return "R_PPC64_GOT_DTPREL16_LO_DS";
+		case 93: return "R_PPC64_GOT_DTPREL16_HI";
+		case 94: return "R_PPC64_GOT_DTPREL16_HA";
+		case 95: return "R_PPC64_TPREL16_DS";
+		case 96: return "R_PPC64_TPREL16_LO_DS";
+		case 97: return "R_PPC64_TPREL16_HIGHER";
+		case 98: return "R_PPC64_TPREL16_HIGHERA";
+		case 99: return "R_PPC64_TPREL16_HIGHEST";
+		case 100: return "R_PPC64_TPREL16_HIGHESTA";
+		case 101: return "R_PPC64_DTPREL16_DS";
+		case 102: return "R_PPC64_DTPREL16_LO_DS";
+		case 103: return "R_PPC64_DTPREL16_HIGHER";
+		case 104: return "R_PPC64_DTPREL16_HIGHERA";
+		case 105: return "R_PPC64_DTPREL16_HIGHEST";
+		case 106: return "R_PPC64_DTPREL16_HIGHESTA";
+		case 107: return "R_PPC64_TLSGD";
+		case 108: return "R_PPC64_TLSLD";
+		case 249: return "R_PPC64_REL16";
+		case 250: return "R_PPC64_REL16_LO";
+		case 251: return "R_PPC64_REL16_HI";
+		case 252: return "R_PPC64_REL16_HA";
+		}
+		break;
+	case EM_RISCV:
+		switch(type) {
+		case 0: return "R_RISCV_NONE";
+		case 1: return "R_RISCV_32";
+		case 2: return "R_RISCV_64";
+		case 3: return "R_RISCV_RELATIVE";
+		case 4: return "R_RISCV_COPY";
+		case 5: return "R_RISCV_JUMP_SLOT";
+		case 6: return "R_RISCV_TLS_DTPMOD32";
+		case 7: return "R_RISCV_TLS_DTPMOD64";
+		case 8: return "R_RISCV_TLS_DTPREL32";
+		case 9: return "R_RISCV_TLS_DTPREL64";
+		case 10: return "R_RISCV_TLS_TPREL32";
+		case 11: return "R_RISCV_TLS_TPREL64";
+		case 16: return "R_RISCV_BRANCH";
+		case 17: return "R_RISCV_JAL";
+		case 18: return "R_RISCV_CALL";
+		case 19: return "R_RISCV_CALL_PLT";
+		case 20: return "R_RISCV_GOT_HI20";
+		case 21: return "R_RISCV_TLS_GOT_HI20";
+		case 22: return "R_RISCV_TLS_GD_HI20";
+		case 23: return "R_RISCV_PCREL_HI20";
+		case 24: return "R_RISCV_PCREL_LO12_I";
+		case 25: return "R_RISCV_PCREL_LO12_S";
+		case 26: return "R_RISCV_HI20";
+		case 27: return "R_RISCV_LO12_I";
+		case 28: return "R_RISCV_LO12_S";
+		case 29: return "R_RISCV_TPREL_HI20";
+		case 30: return "R_RISCV_TPREL_LO12_I";
+		case 31: return "R_RISCV_TPREL_LO12_S";
+		case 32: return "R_RISCV_TPREL_ADD";
+		case 33: return "R_RISCV_ADD8";
+		case 34: return "R_RISCV_ADD16";
+		case 35: return "R_RISCV_ADD32";
+		case 36: return "R_RISCV_ADD64";
+		case 37: return "R_RISCV_SUB8";
+		case 38: return "R_RISCV_SUB16";
+		case 39: return "R_RISCV_SUB32";
+		case 40: return "R_RISCV_SUB64";
+		case 41: return "R_RISCV_GNU_VTINHERIT";
+		case 42: return "R_RISCV_GNU_VTENTRY";
+		case 43: return "R_RISCV_ALIGN";
+		case 44: return "R_RISCV_RVC_BRANCH";
+		case 45: return "R_RISCV_RVC_JUMP";
+		case 46: return "R_RISCV_RVC_LUI";
+		case 47: return "R_RISCV_GPREL_I";
+		case 48: return "R_RISCV_GPREL_S";
+		}
+		break;
+	case EM_S390:
+		switch (type) {
+		case 0: return "R_390_NONE";
+		case 1: return "R_390_8";
+		case 2: return "R_390_12";
+		case 3: return "R_390_16";
+		case 4: return "R_390_32";
+		case 5: return "R_390_PC32";
+		case 6: return "R_390_GOT12";
+		case 7: return "R_390_GOT32";
+		case 8: return "R_390_PLT32";
+		case 9: return "R_390_COPY";
+		case 10: return "R_390_GLOB_DAT";
+		case 11: return "R_390_JMP_SLOT";
+		case 12: return "R_390_RELATIVE";
+		case 13: return "R_390_GOTOFF";
+		case 14: return "R_390_GOTPC";
+		case 15: return "R_390_GOT16";
+		case 16: return "R_390_PC16";
+		case 17: return "R_390_PC16DBL";
+		case 18: return "R_390_PLT16DBL";
+		case 19: return "R_390_PC32DBL";
+		case 20: return "R_390_PLT32DBL";
+		case 21: return "R_390_GOTPCDBL";
+		case 22: return "R_390_64";
+		case 23: return "R_390_PC64";
+		case 24: return "R_390_GOT64";
+		case 25: return "R_390_PLT64";
+		case 26: return "R_390_GOTENT";
+		}
+		break;
+	case EM_SPARC:
+	case EM_SPARCV9:
+		switch(type) {
+		case 0: return "R_SPARC_NONE";
+		case 1: return "R_SPARC_8";
+		case 2: return "R_SPARC_16";
+		case 3: return "R_SPARC_32";
+		case 4: return "R_SPARC_DISP8";
+		case 5: return "R_SPARC_DISP16";
+		case 6: return "R_SPARC_DISP32";
+		case 7: return "R_SPARC_WDISP30";
+		case 8: return "R_SPARC_WDISP22";
+		case 9: return "R_SPARC_HI22";
+		case 10: return "R_SPARC_22";
+		case 11: return "R_SPARC_13";
+		case 12: return "R_SPARC_LO10";
+		case 13: return "R_SPARC_GOT10";
+		case 14: return "R_SPARC_GOT13";
+		case 15: return "R_SPARC_GOT22";
+		case 16: return "R_SPARC_PC10";
+		case 17: return "R_SPARC_PC22";
+		case 18: return "R_SPARC_WPLT30";
+		case 19: return "R_SPARC_COPY";
+		case 20: return "R_SPARC_GLOB_DAT";
+		case 21: return "R_SPARC_JMP_SLOT";
+		case 22: return "R_SPARC_RELATIVE";
+		case 23: return "R_SPARC_UA32";
+		case 24: return "R_SPARC_PLT32";
+		case 25: return "R_SPARC_HIPLT22";
+		case 26: return "R_SPARC_LOPLT10";
+		case 27: return "R_SPARC_PCPLT32";
+		case 28: return "R_SPARC_PCPLT22";
+		case 29: return "R_SPARC_PCPLT10";
+		case 30: return "R_SPARC_10";
+		case 31: return "R_SPARC_11";
+		case 32: return "R_SPARC_64";
+		case 33: return "R_SPARC_OLO10";
+		case 34: return "R_SPARC_HH22";
+		case 35: return "R_SPARC_HM10";
+		case 36: return "R_SPARC_LM22";
+		case 37: return "R_SPARC_PC_HH22";
+		case 38: return "R_SPARC_PC_HM10";
+		case 39: return "R_SPARC_PC_LM22";
+		case 40: return "R_SPARC_WDISP16";
+		case 41: return "R_SPARC_WDISP19";
+		case 42: return "R_SPARC_GLOB_JMP";
+		case 43: return "R_SPARC_7";
+		case 44: return "R_SPARC_5";
+		case 45: return "R_SPARC_6";
+		case 46: return "R_SPARC_DISP64";
+		case 47: return "R_SPARC_PLT64";
+		case 48: return "R_SPARC_HIX22";
+		case 49: return "R_SPARC_LOX10";
+		case 50: return "R_SPARC_H44";
+		case 51: return "R_SPARC_M44";
+		case 52: return "R_SPARC_L44";
+		case 53: return "R_SPARC_REGISTER";
+		case 54: return "R_SPARC_UA64";
+		case 55: return "R_SPARC_UA16";
+		case 56: return "R_SPARC_TLS_GD_HI22";
+		case 57: return "R_SPARC_TLS_GD_LO10";
+		case 58: return "R_SPARC_TLS_GD_ADD";
+		case 59: return "R_SPARC_TLS_GD_CALL";
+		case 60: return "R_SPARC_TLS_LDM_HI22";
+		case 61: return "R_SPARC_TLS_LDM_LO10";
+		case 62: return "R_SPARC_TLS_LDM_ADD";
+		case 63: return "R_SPARC_TLS_LDM_CALL";
+		case 64: return "R_SPARC_TLS_LDO_HIX22";
+		case 65: return "R_SPARC_TLS_LDO_LOX10";
+		case 66: return "R_SPARC_TLS_LDO_ADD";
+		case 67: return "R_SPARC_TLS_IE_HI22";
+		case 68: return "R_SPARC_TLS_IE_LO10";
+		case 69: return "R_SPARC_TLS_IE_LD";
+		case 70: return "R_SPARC_TLS_IE_LDX";
+		case 71: return "R_SPARC_TLS_IE_ADD";
+		case 72: return "R_SPARC_TLS_LE_HIX22";
+		case 73: return "R_SPARC_TLS_LE_LOX10";
+		case 74: return "R_SPARC_TLS_DTPMOD32";
+		case 75: return "R_SPARC_TLS_DTPMOD64";
+		case 76: return "R_SPARC_TLS_DTPOFF32";
+		case 77: return "R_SPARC_TLS_DTPOFF64";
+		case 78: return "R_SPARC_TLS_TPOFF32";
+		case 79: return "R_SPARC_TLS_TPOFF64";
+		}
+		break;
+	case EM_X86_64:
+		switch(type) {
+		case 0: return "R_X86_64_NONE";
+		case 1: return "R_X86_64_64";
+		case 2: return "R_X86_64_PC32";
+		case 3: return "R_X86_64_GOT32";
+		case 4: return "R_X86_64_PLT32";
+		case 5: return "R_X86_64_COPY";
+		case 6: return "R_X86_64_GLOB_DAT";
+		case 7: return "R_X86_64_JUMP_SLOT";
+		case 8: return "R_X86_64_RELATIVE";
+		case 9: return "R_X86_64_GOTPCREL";
+		case 10: return "R_X86_64_32";
+		case 11: return "R_X86_64_32S";
+		case 12: return "R_X86_64_16";
+		case 13: return "R_X86_64_PC16";
+		case 14: return "R_X86_64_8";
+		case 15: return "R_X86_64_PC8";
+		case 16: return "R_X86_64_DTPMOD64";
+		case 17: return "R_X86_64_DTPOFF64";
+		case 18: return "R_X86_64_TPOFF64";
+		case 19: return "R_X86_64_TLSGD";
+		case 20: return "R_X86_64_TLSLD";
+		case 21: return "R_X86_64_DTPOFF32";
+		case 22: return "R_X86_64_GOTTPOFF";
+		case 23: return "R_X86_64_TPOFF32";
+		case 24: return "R_X86_64_PC64";
+		case 25: return "R_X86_64_GOTOFF64";
+		case 26: return "R_X86_64_GOTPC32";
+		case 27: return "R_X86_64_GOT64";
+		case 28: return "R_X86_64_GOTPCREL64";
+		case 29: return "R_X86_64_GOTPC64";
+		case 30: return "R_X86_64_GOTPLT64";
+		case 31: return "R_X86_64_PLTOFF64";
+		case 32: return "R_X86_64_SIZE32";
+		case 33: return "R_X86_64_SIZE64";
+		case 34: return "R_X86_64_GOTPC32_TLSDESC";
+		case 35: return "R_X86_64_TLSDESC_CALL";
+		case 36: return "R_X86_64_TLSDESC";
+		case 37: return "R_X86_64_IRELATIVE";
+		case 38: return "R_X86_64_RELATIVE64";
+		case 41: return "R_X86_64_GOTPCRELX";
+		case 42: return "R_X86_64_REX_GOTPCRELX";
+		}
+		break;
+	}
+
+	snprintf(s_type, sizeof(s_type), "<unknown: %#x>", type);
+	return (s_type);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/elftc_set_timestamps.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,84 @@
+.\" Copyright (c) 2011 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id$
+.\"
+.Dd December 15, 2011
+.Os
+.Dt ELFTC_SET_TIMESTAMPS 3
+.Sh NAME
+.Nm elftc_set_timestamps
+.Nd set file timestamps
+.Sh LIBRARY
+.Lb libelftc
+.Sh SYNOPSIS
+.In libelftc.h
+.Ft int
+.Fn elftc_set_timestamps "const char *filename" "struct stat *sb"
+.Sh DESCRIPTION
+The
+.Fn elftc_set_timestamps
+function is used to set the access and modified time stamps on a file
+based on the contents of a
+.Vt "struct stat"
+descriptor.
+.Pp
+Argument
+.Ar filename
+names an existing file in the file system.
+.Pp
+Argument
+.Ar sb
+points to structure of type
+.Vt "struct stat"
+populated by a prior call to
+.Xr fstat 2
+or
+.Xr stat 2 .
+.Sh IMPLEMENTATION NOTES
+This function will invoke the high-resolution
+.Xr utimes 2
+system call if the underlying operating system supports it.
+On operating systems lacking support for
+.Xr utimes 2 ,
+the function will use lower resolution
+.Xr utime 2
+system call.
+.Sh EXAMPLES
+To set the access and modified times for a new file to those of an
+existing file, use:
+.Bd -literal -offset indent
+struct stat sb;
+const char *existing_filename, *new_filename;
+
+if (stat(existing_filename, &sb) < 0)
+	err(EXIT_FAILURE, "stat failed");
+
+if (elftc_set_timestamps(new_filename, &sb) < 0)
+	err(EXIT_FAILURE, "timestamps could not be set");
+.Ed
+.Sh SEE ALSO
+.Xr fstat 2 ,
+.Xr stat 2 ,
+.Xr utime 2 ,
+.Xr utimes 2 .
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/elftc_set_timestamps.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,85 @@
+/*-
+ * Copyright (c) 2011 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+
+#include "libelftc.h"
+
+#include "_libelftc.h"
+
+ELFTC_VCSID("$Id$");
+
+/*
+ * Determine the field name for the timestamp fields inside a 'struct
+ * stat'.
+ */
+
+#if	defined(__FreeBSD__) || defined(__NetBSD__)
+#define	ATIME	st_atimespec
+#define	MTIME	st_mtimespec
+#define	LIBELFTC_HAVE_UTIMES	1
+#endif
+
+#if	defined(__DragonFly__) || defined(__linux__) || defined(__OpenBSD__)
+#define	ATIME	st_atim
+#define	MTIME	st_mtim
+#define	LIBELFTC_HAVE_UTIMES	1
+#endif
+
+#if	LIBELFTC_HAVE_UTIMES
+#include <sys/time.h>
+#else
+#include <utime.h>
+#endif
+
+int
+elftc_set_timestamps(const char *fn, struct stat *sb)
+{
+#if	LIBELFTC_HAVE_UTIMES
+	/*
+	 * The BSD utimes() system call offers timestamps
+	 * 1-microsecond granularity.
+	 */
+	struct timeval tv[2];
+
+	tv[0].tv_sec = sb->ATIME.tv_sec;
+	tv[0].tv_usec = sb->ATIME.tv_nsec / 1000;
+	tv[1].tv_sec = sb->MTIME.tv_sec;
+	tv[1].tv_usec = sb->MTIME.tv_nsec / 1000;
+
+	return (utimes(fn, tv));
+#else
+	/*
+	 * On OSes without utimes(), fall back to the POSIX utime()
+	 * call, which offers 1-second granularity.
+	 */
+	struct utimbuf utb;
+
+	utb.actime = sb->st_atime;
+	utb.modtime = sb->st_mtime;
+	return (utime(fn, &utb));
+#endif
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/elftc_string_table.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,392 @@
+/*-
+ * Copyright (c) 2013, Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <gelf.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libelftc.h"
+#include "_libelftc.h"
+
+ELFTC_VCSID("$Id: elftc_string_table.c 2869 2013-01-06 13:29:18Z jkoshy $");
+
+#define	ELFTC_STRING_TABLE_DEFAULT_SIZE			(4*1024)
+#define ELFTC_STRING_TABLE_EXPECTED_STRING_SIZE		16
+#define ELFTC_STRING_TABLE_EXPECTED_CHAIN_LENGTH	8
+#define	ELFTC_STRING_TABLE_POOL_SIZE_INCREMENT		(4*1024)
+
+struct _Elftc_String_Table_Entry {
+	int		ste_idx;
+	SLIST_ENTRY(_Elftc_String_Table_Entry) ste_next;
+};
+
+#define	ELFTC_STRING_TABLE_COMPACTION_FLAG	0x1
+#define	ELFTC_STRING_TABLE_LENGTH(st)		((st)->st_len >> 1)
+#define	ELFTC_STRING_TABLE_CLEAR_COMPACTION_FLAG(st) do {		\
+		(st)->st_len &= ~ELFTC_STRING_TABLE_COMPACTION_FLAG;	\
+	} while (0)
+#define	ELFTC_STRING_TABLE_SET_COMPACTION_FLAG(st) do {			\
+		(st)->st_len |= ELFTC_STRING_TABLE_COMPACTION_FLAG;	\
+	} while (0)
+#define	ELFTC_STRING_TABLE_UPDATE_LENGTH(st, len) do {		\
+		(st)->st_len =					\
+		    ((st)->st_len &				\
+			ELFTC_STRING_TABLE_COMPACTION_FLAG) |	\
+		    ((len) << 1);				\
+	} while (0)
+
+struct _Elftc_String_Table {
+	unsigned int		st_len; /* length and flags */
+	int		st_nbuckets;
+	int		st_string_pool_size;
+	char		*st_string_pool;
+	SLIST_HEAD(_Elftc_String_Table_Bucket,
+	    _Elftc_String_Table_Entry) st_buckets[];
+};
+
+static struct _Elftc_String_Table_Entry *
+elftc_string_table_find_hash_entry(Elftc_String_Table *st, const char *string,
+    int *rhashindex)
+{
+	struct _Elftc_String_Table_Entry *ste;
+	int hashindex;
+	char *s;
+
+	hashindex = libelftc_hash_string(string) % st->st_nbuckets;
+
+	if (rhashindex)
+		*rhashindex = hashindex;
+
+	SLIST_FOREACH(ste, &st->st_buckets[hashindex], ste_next) {
+		s = st->st_string_pool + abs(ste->ste_idx);
+
+		assert(s > st->st_string_pool &&
+		    s < st->st_string_pool + st->st_string_pool_size);
+
+		if (strcmp(s, string) == 0)
+			return (ste);
+	}
+
+	return (NULL);
+}
+
+static int
+elftc_string_table_add_to_pool(Elftc_String_Table *st, const char *string)
+{
+	char *newpool;
+	int len, newsize, stlen;
+
+	len = strlen(string) + 1; /* length, including the trailing NUL */
+	stlen = ELFTC_STRING_TABLE_LENGTH(st);
+
+	/* Resize the pool, if needed. */
+	if (stlen + len >= st->st_string_pool_size) {
+		newsize = roundup(st->st_string_pool_size +
+		    ELFTC_STRING_TABLE_POOL_SIZE_INCREMENT,
+		    ELFTC_STRING_TABLE_POOL_SIZE_INCREMENT);
+		if ((newpool = realloc(st->st_string_pool, newsize)) ==
+		    NULL)
+			return (0);
+		st->st_string_pool = newpool;
+		st->st_string_pool_size = newsize;
+	}
+
+	strcpy(st->st_string_pool + stlen, string);
+	ELFTC_STRING_TABLE_UPDATE_LENGTH(st, stlen + len);
+
+	return (stlen);
+}
+
+Elftc_String_Table *
+elftc_string_table_create(int sizehint)
+{
+	int n, nbuckets, tablesize;
+	struct _Elftc_String_Table *st;
+
+	if (sizehint < ELFTC_STRING_TABLE_DEFAULT_SIZE)
+		sizehint = ELFTC_STRING_TABLE_DEFAULT_SIZE;
+
+	nbuckets = sizehint / (ELFTC_STRING_TABLE_EXPECTED_CHAIN_LENGTH *
+	    ELFTC_STRING_TABLE_EXPECTED_STRING_SIZE);
+
+	tablesize = sizeof(struct _Elftc_String_Table) +
+	    nbuckets * sizeof(struct _Elftc_String_Table_Bucket);
+
+	if ((st = malloc(tablesize)) == NULL)
+		return (NULL);
+	if ((st->st_string_pool = malloc(sizehint)) == NULL) {
+		free(st);
+		return (NULL);
+	}
+
+	for (n = 0; n < nbuckets; n++)
+		SLIST_INIT(&st->st_buckets[n]);
+
+	st->st_len = 0;
+	st->st_nbuckets = nbuckets;
+	st->st_string_pool_size = sizehint;
+	*st->st_string_pool = '\0';
+	ELFTC_STRING_TABLE_UPDATE_LENGTH(st, 1);
+
+	return (st);
+}
+
+void
+elftc_string_table_destroy(Elftc_String_Table *st)
+{
+	int n;
+	struct _Elftc_String_Table_Entry *s, *t;
+
+	for (n = 0; n < st->st_nbuckets; n++)
+		SLIST_FOREACH_SAFE(s, &st->st_buckets[n], ste_next, t)
+		    free(s);
+	free(st->st_string_pool);
+	free(st);
+
+	return;
+}
+
+Elftc_String_Table *
+elftc_string_table_from_section(Elf_Scn *scn, int sizehint)
+{
+	int len;
+	Elf_Data *d;
+	GElf_Shdr sh;
+	const char *s, *end;
+	Elftc_String_Table *st;
+
+	/* Verify the type of the section passed in. */
+	if (gelf_getshdr(scn, &sh) == NULL ||
+	    sh.sh_type != SHT_STRTAB) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	if ((d = elf_getdata(scn, NULL)) == NULL ||
+	    d->d_size == 0) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	if ((st = elftc_string_table_create(sizehint)) == NULL)
+		return (NULL);
+
+	s = d->d_buf;
+
+	/*
+	 * Verify that the first byte of the data buffer is '\0'.
+	 */
+	if (*s != '\0') {
+		errno = EINVAL;
+		goto fail;
+	}
+
+	end = s + d->d_size;
+
+	/*
+	 * Skip the first '\0' and insert the strings in the buffer,
+	 * in order.
+	 */
+	for (s += 1; s < end; s += len) {
+		if (elftc_string_table_insert(st, s) == 0)
+			goto fail;
+
+		len = strlen(s) + 1; /* Include space for the trailing NUL. */
+	}
+
+	return (st);
+
+fail:
+	if (st)
+		(void) elftc_string_table_destroy(st);
+
+	return (NULL);
+}
+
+const char *
+elftc_string_table_image(Elftc_String_Table *st, size_t *size)
+{
+	char *r, *s, *end;
+	struct _Elftc_String_Table_Entry *ste;
+	struct _Elftc_String_Table_Bucket *head;
+	int copied, hashindex, offset, length, newsize;
+
+	/*
+	 * For the common case of a string table has not seen
+	 * a string deletion, we can just export the current
+	 * pool.
+	 */
+	if ((st->st_len & ELFTC_STRING_TABLE_COMPACTION_FLAG) == 0) {
+		if (size)
+			*size = ELFTC_STRING_TABLE_LENGTH(st);
+		return (st->st_string_pool);
+	}
+
+	/*
+	 * Otherwise, compact the string table in-place.
+	 */
+	assert(*st->st_string_pool == '\0');
+
+	newsize = 1;
+	end = st->st_string_pool + ELFTC_STRING_TABLE_LENGTH(st);
+
+	for (r = s = st->st_string_pool + 1;
+	     s < end;
+	     s += length, r += copied) {
+
+		copied = 0;
+		length = strlen(s) + 1;
+
+		ste = elftc_string_table_find_hash_entry(st, s,
+		    &hashindex);
+		head = &st->st_buckets[hashindex];
+
+		assert(ste != NULL);
+
+		/* Ignore deleted strings. */
+		if (ste->ste_idx < 0) {
+			SLIST_REMOVE(head, ste, _Elftc_String_Table_Entry,
+			    ste_next);
+			free(ste);
+			continue;
+		}
+
+		/* Move 'live' strings up. */
+		offset = newsize;
+		newsize += length;
+		copied = length;
+
+		if (r == s)	/* Nothing removed yet. */
+			continue;
+
+		memmove(r, s, copied);
+
+		/* Update the index for this entry. */
+		ste->ste_idx = offset;
+	}
+
+	ELFTC_STRING_TABLE_CLEAR_COMPACTION_FLAG(st);
+	ELFTC_STRING_TABLE_UPDATE_LENGTH(st, newsize);
+
+	if (size)
+		*size = newsize;
+
+	return (st->st_string_pool);
+}
+
+size_t
+elftc_string_table_insert(Elftc_String_Table *st, const char *string)
+{
+	int hashindex, idx;
+	struct _Elftc_String_Table_Entry *ste;
+
+	hashindex = 0;
+
+	ste = elftc_string_table_find_hash_entry(st, string, &hashindex);
+
+	assert(hashindex >= 0 && hashindex < st->st_nbuckets);
+
+	if (ste == NULL) {
+		if ((ste = malloc(sizeof(*ste))) == NULL)
+			return (0);
+		if ((ste->ste_idx = elftc_string_table_add_to_pool(st,
+			    string)) == 0) {
+			free(ste);
+			return (0);
+		}
+
+		SLIST_INSERT_HEAD(&st->st_buckets[hashindex], ste, ste_next);
+	}
+
+	idx = ste->ste_idx;
+	if (idx < 0) 		/* Undelete. */
+		ste->ste_idx = idx = (- idx);
+
+	return (idx);
+}
+
+size_t
+elftc_string_table_lookup(Elftc_String_Table *st, const char *string)
+{
+	int hashindex, idx;
+	struct _Elftc_String_Table_Entry *ste;
+
+	ste = elftc_string_table_find_hash_entry(st, string, &hashindex);
+
+	assert(hashindex >= 0 && hashindex < st->st_nbuckets);
+
+	if (ste == NULL || (idx = ste->ste_idx) < 0)
+		return (0);
+
+	return (idx);
+}
+
+int
+elftc_string_table_remove(Elftc_String_Table *st, const char *string)
+{
+	int idx;
+	struct _Elftc_String_Table_Entry *ste;
+
+	ste = elftc_string_table_find_hash_entry(st, string, NULL);
+
+	if (ste == NULL || (idx = ste->ste_idx) < 0)
+		return (ELFTC_FAILURE);
+
+	assert(idx > 0 && idx < (int) ELFTC_STRING_TABLE_LENGTH(st));
+
+	ste->ste_idx = (- idx);
+
+	ELFTC_STRING_TABLE_SET_COMPACTION_FLAG(st);
+
+	return (ELFTC_SUCCESS);
+}
+
+const char *
+elftc_string_table_to_string(Elftc_String_Table *st, size_t offset)
+{
+	const char *s;
+
+	s = st->st_string_pool + offset;
+
+	/*
+	 * Check for:
+	 * - An offset value within pool bounds.
+	 * - A non-NUL byte at the specified offset.
+	 * - The end of the prior string at offset - 1.
+	 */
+	if (offset == 0 || offset >= ELFTC_STRING_TABLE_LENGTH(st) ||
+	    *s == '\0' || *(s - 1) != '\0') {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	return (s);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/elftc_string_table_create.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,227 @@
+.\" Copyright (c) 2012-2013 Joseph Koshy.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elftc_string_table_create.3 2866 2013-01-06 03:20:14Z jkoshy $
+.\"
+.Dd January 5, 2013
+.Os
+.Dt ELFTC_STRING_TABLE_CREATE 3
+.Sh NAME
+.Nm elftc_string_table_create ,
+.Nm elftc_string_table_destroy ,
+.Nm elftc_string_table_from_section ,
+.Nm elftc_string_table_image ,
+.Nm elftc_string_table_insert ,
+.Nm elftc_string_table_lookup ,
+.Nm elftc_string_table_remove ,
+.Nm elftc_string_table_to_string
+.Nd convenience routines for handling ELF string tables
+.Sh SYNOPSIS
+.In libelftc.h
+.Ft "Elftc_String_Table *"
+.Fn elftc_string_table_create "int sizehint"
+.Ft int
+.Fn elftc_string_table_destroy "Elftc_String_Table *table"
+.Ft "Elftc_String_Table *"
+.Fn elftc_string_table_from_section "Elf_Scn *scn" "int sizehint"
+.Ft "const char *"
+.Fo elftc_string_table_image
+.Fa "Elftc_String_Table *table"
+.Fa "size_t *size"
+.Fc
+.Ft size_t
+.Fo elftc_string_table_insert
+.Fa "Elftc_String_Table *table"
+.Fa "const char *string"
+.Fc
+.Ft size_t
+.Fo elftc_string_table_lookup
+.Fa "Elftc_String_Table *table"
+.Fa "const char *string"
+.Fc
+.Ft int
+.Fo elftc_string_table_remove
+.Fa "Elftc_String_Table *table"
+.Fa "const char *string"
+.Fc
+.Ft "const char *"
+.Fo elftc_string_table_to_string
+.Fa "Elftc_String_Table *table"
+.Fa "size_t offset"
+.Fc
+.Sh DESCRIPTION
+This manual page documents convenience routines for handling ELF
+string tables.
+.Pp
+Function
+.Fn elftc_string_table_create
+creates a new, empty string table.
+The argument
+.Ar sizehint
+provides a hint about the expected number of bytes of string data in
+the table.
+If the argument
+.Ar sizehint
+is zero, an implementation-defined default will be used instead.
+.Pp
+Function
+.Fn elftc_string_table_destroy
+destroys the previously allocated string table specified by
+argument
+.Ar table ,
+and frees the internal resources allocated for it.
+.Pp
+Function
+.Fn elftc_string_table_from_section
+creates a new string table and initializes it based on the
+contents of the section specified by argument
+.Ar scn .
+This section must be of type
+.Dv SHT_STRTAB .
+The argument
+.Ar sizehint
+provides a hint about expected number of bytes of string data in the
+table.
+If the value of
+.Ar sizehint
+is zero, an implementation-default will be used instead.
+.Pp
+Function
+.Fn elftc_string_table_image
+returns a pointer to the ELF representation of the contents of the
+string table specified by argument
+.Ar table .
+If argument
+.Ar size
+is not NULL, the size of the ELF representation of the string table is
+stored in the location pointed to by argument
+.Ar size .
+The function
+.Fn elftc_string_table_image
+will compact the string table if the table contains deleted strings.
+The string offsets returned by prior calls to
+.Fn elftc_string_table_insert
+and
+.Fn elftc_string_table_lookup
+should be treated as invalid after a call to this function.
+.Pp
+Function
+.Fn elftc_string_table_insert
+inserts the NUL-terminated string pointed to by argument
+.Ar string
+into the string table specified by argument
+.Ar table ,
+and returns an offset value usable in ELF data structures.
+Multiple insertions of the same content will return the same offset.
+The offset returned will remain valid until the next call to
+.Fn elftc_string_table_image .
+.Pp
+Function
+.Fn elftc_string_table_lookup
+looks up the string referenced by argument
+.Ar string
+in the string table specified by argument
+.Ar table ,
+and if found, returns the offset associated with the string.
+The returned offset will be valid till the next call to function
+.Fn elftc_string_table_image .
+.Pp
+Function
+.Fn elftc_string_table_remove
+removes the string pointed by argument
+.Ar string
+from the string table referenced by argument
+.Ar table ,
+if it is present in the string table.
+.Pp
+Function
+.Fn elftc_string_table_to_string
+returns a pointer to the NUL-terminated string residing at argument
+.Ar offset
+in the string table specified by argument
+.Ar table .
+The value of argument
+.Ar offset
+should be one returned by a prior call to
+.Fn elftc_string_table_insert
+or
+.Fn elftc_string_table_lookup .
+The returned pointer will remain valid until the next call to
+.Fn elftc_string_table_insert
+or
+.Fn elftc_string_table_image .
+.Ss Memory Management
+The
+.Lb libelftc
+library manages its own memory allocations.
+The application should not free the pointers returned by the string
+table functions.
+.El
+.Sh IMPLEMENTATION NOTES
+The current implementation is optimized for the case where strings are
+added to a string table, but rarely removed from it.
+.Pp
+The functions
+.Fn elftc_string_table_insert ,
+.Fn elftc_string_table_lookup ,
+.Fn elftc_string_table_remove
+and
+.Fn elftc_string_table_to_string
+have O(1) asymptotic behavior.
+The function
+.Fn elftc_string_table_image
+can have O(size) asymptotic behavior, where
+.Ar size
+denotes the size of the string table.
+.Sh RETURN VALUES
+Functions
+.Fn elftc_string_table_create
+and
+.Fn elftc_string_table_from_section
+return a valid pointer to an opaque structure of type
+.Vt Elftc_String_Table
+on success, or NULL in case of an error.
+.Pp
+The function
+.Fn elftc_string_table_image
+returns a pointer to an in-memory representation of an ELF string
+table on success, or NULL in case of an error.
+.Pp
+Functions
+.Fn elftc_string_table_insert
+and
+.Fn elftc_string_table_lookup
+return a non-zero offset on success, or zero in case of an error.
+.Pp
+Function
+.Fn elftc_string_table_remove
+returns a positive value on success, or zero in case of an error.
+.Pp
+Function
+.Fn elftc_string_table_to_string
+returns a valid pointer on success, or NULL in case of an error.
+.Sh SEE ALSO
+.Xr dwarf 3 ,
+.Xr elf 3 ,
+.Xr elftc 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/elftc_timestamp.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,79 @@
+.\" Copyright (c) 2016 The FreeBSD Foundation.  All rights reserved.
+.\"
+.\" This documentation was written by Ed Maste under sponsorship of
+.\" the FreeBSD Foundation.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by the author and contributors ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  In no event shall the author or contributors be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id$
+.\"
+.Dd August 24, 2016
+.Os
+.Dt ELFTC_TIMESTAMP 3
+.Sh NAME
+.Nm elftc_timestamp
+.Nd return the current or environment-provided timestamp
+.Sh LIBRARY
+.Lb libelftc
+.Sh SYNOPSIS
+.In libelftc.h
+.Ft int
+.Fo elftc_timestamp
+.Fa "time_t *timestamp"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn elftc_timestamp
+function returns a timestamp supplied by the
+.Ev SOURCE_DATE_EPOCH
+environment variable, or the current time provided by
+.Xr time 3
+if the environment variable is not set.
+.Pp
+The
+.Ar timestamp
+argument specifies a pointer to the location where the timestamp will be
+stored.
+.Sh RETURN VALUE
+Function
+.Fn elftc_timestamp
+returns 0 on success, and -1 in the event of an error.
+.Sh ERRORS
+The
+.Fn elftc_timestamp
+function may fail with the following errors:
+.Bl -tag -width ".Bq Er ERANGE"
+.It Bq Er EINVAL
+.Ev SOURCE_DATE_EPOCH
+contains invalid characters.
+.It Bq Er ERANGE
+.Ev SOURCE_DATE_EPOCH
+specifies a negative value or a value that cannot be stored in a
+time_t.
+.El
+The
+.Fn elftc_timestamp
+function may also fail for any of the reasons described in
+.Xr strtoll 3 .
+.Sh SEE ALSO
+.Xr strtoll 3 ,
+.Xr time 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/elftc_timestamp.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 2016 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Ed Maste under sponsorship
+ * of the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+#include <libelftc.h>
+
+int
+elftc_timestamp(time_t *timestamp)
+{
+	long long source_date_epoch;
+	char *env, *eptr;
+
+	if ((env = getenv("SOURCE_DATE_EPOCH")) != NULL) {
+		errno = 0;
+		source_date_epoch = strtoll(env, &eptr, 10);
+		if (*eptr != '\0')
+			errno = EINVAL;
+		if (source_date_epoch < 0)
+			errno = ERANGE;
+		if (errno != 0)
+			return (-1);
+		*timestamp = source_date_epoch;
+		return (0);
+	}
+	*timestamp = time(NULL);
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/elftc_version.3	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,79 @@
+.\" Copyright (c) 2011,2012 Joseph Koshy.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" This software is provided by Joseph Koshy ``as is'' and
+.\" any express or implied warranties, including, but not limited to, the
+.\" implied warranties of merchantability and fitness for a particular purpose
+.\" are disclaimed.  in no event shall Joseph Koshy be liable
+.\" for any direct, indirect, incidental, special, exemplary, or consequential
+.\" damages (including, but not limited to, procurement of substitute goods
+.\" or services; loss of use, data, or profits; or business interruption)
+.\" however caused and on any theory of liability, whether in contract, strict
+.\" liability, or tort (including negligence or otherwise) arising in any way
+.\" out of the use of this software, even if advised of the possibility of
+.\" such damage.
+.\"
+.\" $Id: elftc_version.3 2828 2012-12-30 04:41:27Z jkoshy $
+.\"
+.Dd December 30, 2012
+.Os
+.Dt ELFTC_VERSION 3
+.Sh NAME
+.Nm elftc_version
+.Nd return a project-wide version identifier string
+.Sh LIBRARY
+.Lb libelftc
+.Sh SYNOPSIS
+.In libelftc.h
+.Ft const char *
+.Fn elftc_version void
+.Sh DESCRIPTION
+Function
+.Fn elftc_version
+returns a project-wide identifier string that encodes the source
+revision of the project source tree.
+.Pp
+The returned identifier has four space-separated fields:
+.Bl -tag -width ".Em Project Branch"
+.It Em "Project-Name"
+This is always
+.Dq elftoolchain .
+.It Em "Project-Branch"
+The branch name for the project source tree.
+.It Em "Build-OS"
+The operating system that the tool chain was compiled for.
+.It Em "Version-Number"
+A tree-wide version number extracted from the version control
+system in use.
+.El
+.Sh RETURN VALUE
+Function
+.Fn elftc_program_version
+returns a pointer to an internal character buffer.
+.Sh EXAMPLES
+To retrieve and print the current toolchain version identifier, use:
+.Bd -literal -offset indent
+#include <sys/types.h>
+#include <libelftc.h>
+
+(void) printf("%s\en", elftc_version());
+.Ed
+.Pp
+On the HEAD branch of the project's sources, when checked out using
+Subversion and compiled on a NetBSD host, this would print:
+.D1 Dq elftoolchain HEAD NetBSD svn: Ns Em REVINFO
+where
+.Em REVINFO
+would be the current revision information for the project source tree.
+.Sh ERRORS
+Function
+.Fn elftc_program_version
+always succeeds.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/libelftc.h	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,100 @@
+/*-
+ * Copyright (c) 2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: users/kaiwang27/elftc/libelftc.h 392 2009-05-31 19:17:46Z kaiwang27 $
+ * $Id: libelftc.h 3489 2016-08-31 00:12:15Z emaste $
+ */
+
+#ifndef	_LIBELFTC_H_
+#define	_LIBELFTC_H_
+
+#include <sys/stat.h>
+
+#include <libelf.h>
+
+/*
+ * Types meant to be opaque to the consumers of these APIs.
+ */
+typedef struct _Elftc_Bfd_Target Elftc_Bfd_Target;
+typedef struct _Elftc_String_Table Elftc_String_Table;
+
+/* Target types. */
+typedef enum {
+	ETF_NONE,
+	ETF_ELF,
+	ETF_BINARY,
+	ETF_SREC,
+	ETF_IHEX,
+	ETF_PE,
+	ETF_EFI,
+} Elftc_Bfd_Target_Flavor;
+
+/*
+ * Demangler flags.
+ */
+
+/* Name mangling style. */
+#define	ELFTC_DEM_UNKNOWN	0x00000000U /* Not specified. */
+#define	ELFTC_DEM_ARM		0x00000001U /* C++ Ann. Ref. Manual. */
+#define	ELFTC_DEM_GNU2		0x00000002U /* GNU version 2. */
+#define	ELFTC_DEM_GNU3		0x00000004U /* GNU version 3. */
+
+/* Demangling behaviour control. */
+#define ELFTC_DEM_NOPARAM	0x00010000U
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+Elftc_Bfd_Target	*elftc_bfd_find_target(const char *_tgt_name);
+Elftc_Bfd_Target_Flavor	 elftc_bfd_target_flavor(Elftc_Bfd_Target *_tgt);
+unsigned int	elftc_bfd_target_byteorder(Elftc_Bfd_Target *_tgt);
+unsigned int	elftc_bfd_target_class(Elftc_Bfd_Target *_tgt);
+unsigned int	elftc_bfd_target_machine(Elftc_Bfd_Target *_tgt);
+int		elftc_copyfile(int _srcfd,  int _dstfd);
+int		elftc_demangle(const char *_mangledname, char *_buffer,
+    size_t _bufsize, unsigned int _flags);
+const char	*elftc_reloc_type_str(unsigned int mach, unsigned int type);
+int		elftc_set_timestamps(const char *_filename, struct stat *_sb);
+Elftc_String_Table	*elftc_string_table_create(int _hint);
+void		elftc_string_table_destroy(Elftc_String_Table *_table);
+Elftc_String_Table	*elftc_string_table_from_section(Elf_Scn *_scn,
+    int _hint);
+const char	*elftc_string_table_image(Elftc_String_Table *_table,
+    size_t *_sz);
+size_t		elftc_string_table_insert(Elftc_String_Table *_table,
+    const char *_string);
+size_t		elftc_string_table_lookup(Elftc_String_Table *_table,
+    const char *_string);
+int		elftc_string_table_remove(Elftc_String_Table *_table,
+    const char *_string);
+const char	*elftc_string_table_to_string(Elftc_String_Table *_table,
+    size_t offset);
+int		elftc_timestamp(time_t *_timestamp);
+const char	*elftc_version(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _LIBELFTC_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,463 @@
+/*-
+ * Copyright (c) 2008,2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <libelf.h>
+#include <libelftc.h>
+
+#include "_libelftc.h"
+
+ELFTC_VCSID("$Id: libelftc_bfdtarget.c 3516 2017-02-10 02:33:08Z emaste $");
+
+struct _Elftc_Bfd_Target _libelftc_targets[] = {
+
+	{
+		.bt_name = "binary",
+		.bt_type = ETF_BINARY,
+	},
+
+	{
+		.bt_name      = "elf32-avr",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2LSB,
+		.bt_elfclass  = ELFCLASS32,
+		.bt_machine   = EM_AVR,
+	},
+
+	{
+		.bt_name      = "elf32-big",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2MSB,
+		.bt_elfclass  = ELFCLASS32,
+	},
+
+	{
+		.bt_name      = "elf32-bigarm",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2MSB,
+		.bt_elfclass  = ELFCLASS32,
+		.bt_machine   = EM_ARM,
+	},
+
+	{
+		.bt_name      = "elf32-bigmips",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2MSB,
+		.bt_elfclass  = ELFCLASS32,
+		.bt_machine   = EM_MIPS,
+	},
+
+	{
+		.bt_name      = "elf32-i386",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2LSB,
+		.bt_elfclass  = ELFCLASS32,
+		.bt_machine   = EM_386,
+	},
+
+	{
+		.bt_name      = "elf32-i386-freebsd",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2LSB,
+		.bt_elfclass  = ELFCLASS32,
+		.bt_machine   = EM_386,
+		.bt_osabi     = ELFOSABI_FREEBSD,
+	},
+
+	{
+		.bt_name      = "elf32-ia64-big",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2MSB,
+		.bt_elfclass  = ELFCLASS32,
+		.bt_machine   = EM_IA_64,
+	},
+
+	{
+		.bt_name      = "elf32-little",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2LSB,
+		.bt_elfclass  = ELFCLASS32,
+	},
+
+	{
+		.bt_name      = "elf32-littlearm",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2LSB,
+		.bt_elfclass  = ELFCLASS32,
+		.bt_machine   = EM_ARM,
+	},
+
+	{
+		.bt_name      = "elf32-littlemips",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2LSB,
+		.bt_elfclass  = ELFCLASS32,
+		.bt_machine   = EM_MIPS,
+	},
+
+	{
+		.bt_name      = "elf32-powerpc",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2MSB,
+		.bt_elfclass  = ELFCLASS32,
+		.bt_machine   = EM_PPC,
+	},
+
+	{
+		.bt_name      = "elf32-powerpc-freebsd",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2MSB,
+		.bt_elfclass  = ELFCLASS32,
+		.bt_machine   = EM_PPC,
+		.bt_osabi     = ELFOSABI_FREEBSD,
+	},
+
+	{
+		.bt_name      = "elf32-powerpcle",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2LSB,
+		.bt_elfclass  = ELFCLASS32,
+		.bt_machine   = EM_PPC,
+	},
+
+	{
+		.bt_name      = "elf32-sh",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2MSB,
+		.bt_elfclass  = ELFCLASS32,
+		.bt_machine   = EM_SH,
+	},
+
+	{
+		.bt_name      = "elf32-shl",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2LSB,
+		.bt_elfclass  = ELFCLASS32,
+		.bt_machine   = EM_SH,
+	},
+
+	{
+		.bt_name      = "elf32-sh-nbsd",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2MSB,
+		.bt_elfclass  = ELFCLASS32,
+		.bt_machine   = EM_SH,
+		.bt_osabi     = ELFOSABI_NETBSD,
+	},
+
+	{
+		.bt_name      = "elf32-shl-nbsd",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2LSB,
+		.bt_elfclass  = ELFCLASS32,
+		.bt_machine   = EM_SH,
+		.bt_osabi     = ELFOSABI_NETBSD,
+	},
+
+	{
+		.bt_name      = "elf32-shbig-linux",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2MSB,
+		.bt_elfclass  = ELFCLASS32,
+		.bt_machine   = EM_SH,
+		.bt_osabi     = ELFOSABI_LINUX,
+	},
+
+	{
+		.bt_name      = "elf32-sh-linux",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2LSB,
+		.bt_elfclass  = ELFCLASS32,
+		.bt_machine   = EM_SH,
+		.bt_osabi     = ELFOSABI_LINUX,
+	},
+
+	{
+		.bt_name      = "elf32-sparc",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2MSB,
+		.bt_elfclass  = ELFCLASS32,
+		.bt_machine   = EM_SPARC,
+	},
+
+	{
+		.bt_name      = "elf32-tradbigmips",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2MSB,
+		.bt_elfclass  = ELFCLASS32,
+		.bt_machine   = EM_MIPS,
+	},
+
+	{
+		.bt_name      = "elf32-tradlittlemips",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2LSB,
+		.bt_elfclass  = ELFCLASS32,
+		.bt_machine   = EM_MIPS,
+	},
+
+	{
+		.bt_name      = "elf64-alpha",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2LSB,
+		.bt_elfclass  = ELFCLASS64,
+		.bt_machine   = EM_ALPHA,
+	},
+
+	{
+		.bt_name      = "elf64-alpha-freebsd",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2LSB,
+		.bt_elfclass  = ELFCLASS64,
+		.bt_machine   = EM_ALPHA,
+		.bt_osabi     = ELFOSABI_FREEBSD
+	},
+
+	{
+		.bt_name      = "elf64-big",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2MSB,
+		.bt_elfclass  = ELFCLASS64,
+	},
+
+	{
+		.bt_name      = "elf64-bigmips",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2MSB,
+		.bt_elfclass  = ELFCLASS64,
+		.bt_machine   = EM_MIPS,
+	},
+
+	{
+		.bt_name      = "elf64-ia64-big",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2MSB,
+		.bt_elfclass  = ELFCLASS64,
+		.bt_machine   = EM_IA_64,
+	},
+
+	{
+		.bt_name      = "elf64-ia64-little",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2LSB,
+		.bt_elfclass  = ELFCLASS64,
+		.bt_machine   = EM_IA_64,
+	},
+
+	{
+		.bt_name      = "elf64-little",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2LSB,
+		.bt_elfclass  = ELFCLASS64,
+	},
+
+	{
+		.bt_name      = "elf64-littleaarch64",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2LSB,
+		.bt_elfclass  = ELFCLASS64,
+		.bt_machine   = EM_AARCH64,
+	},
+
+	{
+		.bt_name      = "elf64-littlemips",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2LSB,
+		.bt_elfclass  = ELFCLASS64,
+		.bt_machine   = EM_MIPS,
+	},
+
+	{
+		.bt_name      = "elf64-powerpc",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2MSB,
+		.bt_elfclass  = ELFCLASS64,
+		.bt_machine   = EM_PPC64,
+	},
+
+	{
+		.bt_name      = "elf64-powerpc-freebsd",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2MSB,
+		.bt_elfclass  = ELFCLASS64,
+		.bt_machine   = EM_PPC64,
+		.bt_osabi     = ELFOSABI_FREEBSD,
+	},
+
+	{
+		.bt_name      = "elf64-powerpcle",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2LSB,
+		.bt_elfclass  = ELFCLASS64,
+		.bt_machine   = EM_PPC64,
+	},
+
+	{
+		.bt_name      = "elf64-sh64",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2MSB,
+		.bt_elfclass  = ELFCLASS64,
+		.bt_machine   = EM_SH,
+	},
+
+	{
+		.bt_name      = "elf64-sh64l",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2LSB,
+		.bt_elfclass  = ELFCLASS64,
+		.bt_machine   = EM_SH,
+	},
+
+	{
+		.bt_name      = "elf64-sh64-nbsd",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2MSB,
+		.bt_elfclass  = ELFCLASS64,
+		.bt_machine   = EM_SH,
+		.bt_osabi     = ELFOSABI_NETBSD,
+	},
+
+	{
+		.bt_name      = "elf64-sh64l-nbsd",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2LSB,
+		.bt_elfclass  = ELFCLASS64,
+		.bt_machine   = EM_SH,
+		.bt_osabi     = ELFOSABI_NETBSD,
+	},
+
+	{
+		.bt_name      = "elf64-sh64big-linux",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2MSB,
+		.bt_elfclass  = ELFCLASS64,
+		.bt_machine   = EM_SH,
+		.bt_osabi     = ELFOSABI_LINUX,
+	},
+
+	{
+		.bt_name      = "elf64-sh64-linux",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2LSB,
+		.bt_elfclass  = ELFCLASS64,
+		.bt_machine   = EM_SH,
+		.bt_osabi     = ELFOSABI_LINUX,
+	},
+
+	{
+		.bt_name      = "elf64-sparc",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2MSB,
+		.bt_elfclass  = ELFCLASS64,
+		.bt_machine   = EM_SPARCV9,
+	},
+
+	{
+		.bt_name      = "elf64-sparc-freebsd",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2MSB,
+		.bt_elfclass  = ELFCLASS64,
+		.bt_machine   = EM_SPARCV9,
+		.bt_osabi     = ELFOSABI_FREEBSD
+	},
+
+	{
+		.bt_name      = "elf64-tradbigmips",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2MSB,
+		.bt_elfclass  = ELFCLASS64,
+		.bt_machine   = EM_MIPS,
+	},
+
+	{
+		.bt_name      = "elf64-tradlittlemips",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2LSB,
+		.bt_elfclass  = ELFCLASS64,
+		.bt_machine   = EM_MIPS,
+	},
+
+	{
+		.bt_name      = "elf64-x86-64",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder =	ELFDATA2LSB,
+		.bt_elfclass  = ELFCLASS64,
+		.bt_machine   = EM_X86_64,
+	},
+
+	{
+		.bt_name      = "elf64-x86-64-freebsd",
+		.bt_type      = ETF_ELF,
+		.bt_byteorder = ELFDATA2LSB,
+		.bt_elfclass  = ELFCLASS64,
+		.bt_machine   = EM_X86_64,
+		.bt_osabi     = ELFOSABI_FREEBSD
+	},
+
+	{
+		.bt_name = "ihex",
+		.bt_type = ETF_IHEX,
+	},
+
+	{
+		.bt_name = "srec",
+		.bt_type = ETF_SREC,
+	},
+
+	{
+		.bt_name = "symbolsrec",
+		.bt_type = ETF_SREC,
+	},
+
+	{
+		.bt_name    = "efi-app-ia32",
+		.bt_type    = ETF_EFI,
+		.bt_machine = EM_386,
+	},
+
+	{
+		.bt_name    = "efi-app-x86_64",
+		.bt_type    = ETF_EFI,
+		.bt_machine = EM_X86_64,
+	},
+
+	{
+		.bt_name    = "pei-i386",
+		.bt_type    = ETF_PE,
+		.bt_machine = EM_386,
+	},
+
+	{
+		.bt_name    = "pei-x86-64",
+		.bt_type    = ETF_PE,
+		.bt_machine = EM_X86_64,
+	},
+
+	{
+		.bt_name = NULL,
+		.bt_type = ETF_NONE,
+	},
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/libelftc_dem_arm.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,1216 @@
+/*-
+ * Copyright (c) 2008 Hyogeol Lee <hyogeollee@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <libelftc.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "_libelftc.h"
+
+ELFTC_VCSID("$Id: libelftc_dem_arm.c 3513 2016-12-29 07:04:22Z kaiwang27 $");
+
+/**
+ * @file cpp_demangle_arm.c
+ * @brief Decode function name encoding in ARM.
+ *
+ * Function name encoding in "The Annotated C++ Reference Manual".
+ *
+ * Ref : "The Annotated C++ Reference Manual", Margaet A.Ellis,
+ *  Bjarne Stroustrup, AT&T Bell Laboratories 1990, pp 122-126.
+ */
+
+enum encode_type {
+	ENCODE_FUNC, ENCODE_OP, ENCODE_OP_CT, ENCODE_OP_DT, ENCODE_OP_USER
+};
+
+struct cstring {
+	char	*buf;
+	size_t	size;
+};
+
+struct demangle_data {
+	bool	ptr, ref, cnst, array;
+	struct cstring array_str;
+	const char *p;
+	enum encode_type type;
+	struct vector_str vec;
+	struct vector_str arg;
+};
+
+#define SIMPLE_HASH(x,y)	(64 * x + y)
+#define VEC_PUSH_STR(d,s)	vector_str_push((d), (s), strlen((s)))
+#define	CPP_DEMANGLE_ARM_TRY	128
+
+static void	dest_cstring(struct cstring *);
+static void	dest_demangle_data(struct demangle_data *);
+static bool	init_cstring(struct cstring *, size_t);
+static bool	init_demangle_data(struct demangle_data *);
+static bool	push_CTDT(const char *, size_t, struct vector_str *);
+static bool	read_array(struct demangle_data *);
+static bool	read_class(struct demangle_data *);
+static bool	read_func(struct demangle_data *);
+static bool	read_func_name(struct demangle_data *);
+static bool	read_func_ptr(struct demangle_data *);
+static bool	read_memptr(struct demangle_data *);
+static bool	read_op(struct demangle_data *);
+static bool	read_op_user(struct demangle_data *);
+static bool	read_qual_name(struct demangle_data *);
+static int	read_subst(struct demangle_data *);
+static int	read_subst_iter(struct demangle_data *);
+static bool	read_type(struct demangle_data *);
+
+/**
+ * @brief Decode the input string by the ARM style.
+ *
+ * @return New allocated demangled string or NULL if failed.
+ */
+char *
+cpp_demangle_ARM(const char *org)
+{
+	struct demangle_data d;
+	size_t arg_begin, arg_len;
+	unsigned int try;
+	char *rtn, *arg;
+
+	if (org == NULL)
+		return (NULL);
+
+	if (init_demangle_data(&d) == false)
+		return (NULL);
+
+	try = 0;
+	rtn = NULL;
+
+	d.p = org;
+	if (read_func_name(&d) == false)
+		goto clean;
+
+	if (d.type == ENCODE_OP_CT) {
+		if (push_CTDT("::", 2, &d.vec) == false)
+			goto clean;
+
+		goto flat;
+	}
+
+	if (d.type == ENCODE_OP_DT) {
+		if (push_CTDT("::~", 3, &d.vec) == false)
+			goto clean;
+
+		goto flat;
+	}
+
+	if (d.type == ENCODE_OP_USER)
+		goto flat;
+
+	/* function type */
+	if (*d.p != 'F')
+		goto clean;
+	++d.p;
+
+	/* start argument types */
+	if (VEC_PUSH_STR(&d.vec, "(") == false)
+		goto clean;
+
+	for (;;) {
+		if (*d.p == 'T') {
+			const int rtn_subst = read_subst(&d);
+
+			if (rtn_subst == -1)
+				goto clean;
+			else if (rtn_subst == 1)
+				break;
+
+			continue;
+		}
+
+		if (*d.p == 'N') {
+			const int rtn_subst_iter = read_subst_iter(&d);
+
+			if (rtn_subst_iter == -1)
+				goto clean;
+			else if(rtn_subst_iter == 1)
+				break;
+
+			continue;
+		}
+
+		arg_begin = d.vec.size;
+
+		if (read_type(&d) == false)
+			goto clean;
+
+		if (d.ptr == true) {
+			if (VEC_PUSH_STR(&d.vec, "*") == false)
+				goto clean;
+
+			d.ptr = false;
+		}
+
+		if (d.ref == true) {
+			if (VEC_PUSH_STR(&d.vec, "&") == false)
+				goto clean;
+
+			d.ref = false;
+		}
+
+		if (d.cnst == true) {
+			if (VEC_PUSH_STR(&d.vec, " const") == false)
+				goto clean;
+
+			d.cnst = false;
+		}
+
+		if (d.array == true) {
+			if (vector_str_push(&d.vec, d.array_str.buf,
+				d.array_str.size) == false)
+				goto clean;
+
+			dest_cstring(&d.array_str);
+			d.array = false;
+		}
+
+		if (*d.p == '\0')
+			break;
+
+		if ((arg = vector_str_substr(&d.vec, arg_begin, d.vec.size - 1,
+			    &arg_len)) == NULL)
+			goto clean;
+
+		if (vector_str_push(&d.arg, arg, arg_len) == false)
+			goto clean;
+
+		free(arg);
+
+		if (VEC_PUSH_STR(&d.vec, ", ") == false)
+			goto clean;
+
+		if (++try > CPP_DEMANGLE_ARM_TRY)
+			goto clean;
+	}
+
+	/* end argument types */
+	if (VEC_PUSH_STR(&d.vec, ")") == false)
+		goto clean;
+
+flat:
+	rtn = vector_str_get_flat(&d.vec, NULL);
+clean:
+	dest_demangle_data(&d);
+
+	return (rtn);
+}
+
+/**
+ * @brief Test input string is encoded by the ARM style.
+ *
+ * @return True if input string is encoded by the ARM style.
+ */
+bool
+is_cpp_mangled_ARM(const char *org)
+{
+
+	if (org == NULL)
+		return (false);
+
+	return (strstr(org, "__") != NULL);
+}
+
+static void
+dest_cstring(struct cstring *s)
+{
+
+	if (s == NULL)
+		return;
+
+	free(s->buf);
+	s->buf = NULL;
+	s->size = 0;
+}
+
+static void
+dest_demangle_data(struct demangle_data *d)
+{
+
+	if (d != NULL) {
+		vector_str_dest(&d->arg);
+		vector_str_dest(&d->vec);
+
+		dest_cstring(&d->array_str);
+	}
+}
+
+static bool
+init_cstring(struct cstring *s, size_t len)
+{
+
+	if (s == NULL || len <= 1)
+		return (false);
+
+	if ((s->buf = malloc(sizeof(char) * len)) == NULL)
+		return (false);
+
+	s->size = len - 1;
+
+	return (true);
+}
+
+static bool
+init_demangle_data(struct demangle_data *d)
+{
+
+	if (d == NULL)
+		return (false);
+
+	d->ptr = false;
+	d->ref = false;
+	d->cnst = false;
+	d->array = false;
+
+	d->array_str.buf = NULL;
+	d->array_str.size = 0;
+
+	d->type = ENCODE_FUNC;
+
+	if (vector_str_init(&d->vec) == false)
+		return (false);
+
+	if (vector_str_init(&d->arg) == false) {
+		vector_str_dest(&d->vec);
+
+		return (false);
+	}
+
+	return (true);
+}
+
+static bool
+push_CTDT(const char *s, size_t l, struct vector_str *v)
+{
+
+	if (s == NULL || l == 0 || v == NULL)
+		return (false);
+
+	if (vector_str_push(v, s, l) == false)
+		return (false);
+
+	assert(v->size > 1);
+	if (VEC_PUSH_STR(v, v->container[v->size - 2]) == false)
+		return (false);
+
+	if (VEC_PUSH_STR(v, "()") == false)
+		return (false);
+
+	return (true);
+}
+
+static bool
+read_array(struct demangle_data *d)
+{
+	size_t len;
+	const char *end;
+
+	if (d == NULL || d->p == NULL)
+		return (false);
+
+	end = d->p;
+	assert(end != NULL);
+
+	for (;;) {
+		if (*end == '\0')
+			return (false);
+
+		if (ELFTC_ISDIGIT(*end) == 0)
+			break;
+
+		++end;
+	}
+
+	if (*end != '_')
+		return (false);
+
+	len = end - d->p;
+	assert(len > 0);
+
+	dest_cstring(&d->array_str);
+	if (init_cstring(&d->array_str, len + 3) == false)
+		return (false);
+
+	strncpy(d->array_str.buf + 1, d->p, len);
+	*d->array_str.buf = '[';
+	*(d->array_str.buf + len + 1) = ']';
+
+	d->array = true;
+	d->p = end + 1;
+
+	return (true);
+}
+
+static bool
+read_class(struct demangle_data *d)
+{
+	size_t len;
+	char *str;
+
+	if (d == NULL)
+		return (false);
+
+	len = strtol(d->p, &str, 10);
+	if (len == 0 && (errno == EINVAL || errno == ERANGE))
+		return (false);
+
+	assert(len > 0);
+	assert(str != NULL);
+
+	if (vector_str_push(&d->vec, str, len) == false)
+		return (false);
+
+	d->p = str + len;
+
+	return (true);
+}
+
+static bool
+read_func(struct demangle_data *d)
+{
+	size_t len;
+	const char *name;
+	char *delim;
+
+	if (d == NULL)
+		return (false);
+
+	assert(d->p != NULL && "d->p (org str) is NULL");
+	if ((delim = strstr(d->p, "__")) == NULL)
+		return (false);
+
+	len = delim - d->p;
+	assert(len != 0);
+
+	name = d->p;
+
+	d->p = delim + 2;
+
+	if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {
+		++d->p;
+
+		if (read_qual_name(d) == false)
+			return (false);
+	} else if (ELFTC_ISDIGIT(*d->p)) {
+		if (read_class(d) == false)
+			return (false);
+
+		if (VEC_PUSH_STR(&d->vec, "::") == false)
+			return (false);
+	}
+
+	if (vector_str_push(&d->vec, name, len) == false)
+		return (false);
+
+	return (true);
+}
+
+static bool
+read_func_name(struct demangle_data *d)
+{
+	size_t len;
+	bool rtn;
+	char *op_name;
+
+	if (d == NULL)
+		return (false);
+
+	rtn = false;
+	op_name = NULL;
+
+	assert(d->p != NULL && "d->p (org str) is NULL");
+
+	if (*d->p == '_' && *(d->p + 1) == '_') {
+		d->p += 2;
+
+		d->type = ENCODE_OP;
+		if (read_op(d) == false)
+			return (false);
+
+		if (d->type == ENCODE_OP_CT || d->type == ENCODE_OP_DT ||
+		    d->type == ENCODE_OP_USER)
+			return (true);
+
+		/* skip "__" */
+		d->p += 2;
+
+		/* assume delimiter is removed */
+		if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {
+			++d->p;
+
+			assert(d->vec.size > 0);
+
+			len = strlen(d->vec.container[d->vec.size - 1]);
+			if ((op_name = malloc(sizeof(char) * (len + 1)))
+			    == NULL)
+				return (false);
+
+			snprintf(op_name, len + 1, "%s",
+			    d->vec.container[d->vec.size - 1]);
+			vector_str_pop(&d->vec);
+
+			if (read_qual_name(d) == false)
+				goto clean;
+
+			if (VEC_PUSH_STR(&d->vec, "::") == false)
+				goto clean;
+
+			if (vector_str_push(&d->vec, op_name, len) == false)
+				goto clean;
+
+			rtn = true;
+		} else if (ELFTC_ISDIGIT(*d->p)) {
+			assert(d->vec.size > 0);
+
+			len = strlen(d->vec.container[d->vec.size - 1]);
+			if ((op_name = malloc(sizeof(char) * (len + 1)))
+			    == NULL)
+				return (false);
+
+			snprintf(op_name, len + 1, "%s",
+			    d->vec.container[d->vec.size - 1]);
+			vector_str_pop(&d->vec);
+
+			if (read_class(d) == false)
+				goto clean;
+
+			if (VEC_PUSH_STR(&d->vec, "::") == false)
+				goto clean;
+
+			if (vector_str_push(&d->vec, op_name, len) == false)
+				goto clean;
+
+			rtn = true;
+		}
+	} else
+		return (read_func(d));
+
+clean:
+	free(op_name);
+
+	return (rtn);
+}
+
+/* Read function ptr type */
+static bool
+read_func_ptr(struct demangle_data *d)
+{
+	struct demangle_data fptr;
+	size_t arg_len, rtn_len;
+	char *arg_type, *rtn_type;
+	int lim;
+
+	if (d == NULL)
+		return (false);
+
+	if (init_demangle_data(&fptr) == false)
+		return (false);
+
+	fptr.p = d->p + 1;
+	lim = 0;
+	arg_type = NULL;
+	rtn_type = NULL;
+
+	for (;;) {
+		if (read_type(&fptr) == false) {
+			dest_demangle_data(&fptr);
+
+			return (false);
+		}
+
+		if (fptr.ptr == true) {
+			if (VEC_PUSH_STR(&fptr.vec, "*") == false) {
+				dest_demangle_data(&fptr);
+
+				return (false);
+			}
+
+			fptr.ptr = false;
+		}
+
+		if (fptr.ref == true) {
+			if (VEC_PUSH_STR(&fptr.vec, "&") == false) {
+				dest_demangle_data(&fptr);
+
+				return (false);
+			}
+
+			fptr.ref = false;
+		}
+
+		if (fptr.cnst == true) {
+			if (VEC_PUSH_STR(&fptr.vec, " const") == false) {
+				dest_demangle_data(&fptr);
+
+				return (false);
+			}
+
+			fptr.cnst = false;
+		}
+
+		if (*fptr.p == '_')
+			break;
+
+		if (VEC_PUSH_STR(&fptr.vec, ", ") == false) {
+			dest_demangle_data(&fptr);
+
+			return (false);
+		}
+
+		if (++lim > CPP_DEMANGLE_ARM_TRY) {
+
+			dest_demangle_data(&fptr);
+
+			return (false);
+		}
+	}
+
+	arg_type = vector_str_get_flat(&fptr.vec, &arg_len);
+	/* skip '_' */
+	d->p = fptr.p + 1;
+
+	dest_demangle_data(&fptr);
+
+	if (init_demangle_data(&fptr) == false) {
+		free(arg_type);
+
+		return (false);
+	}
+
+	fptr.p = d->p;
+	lim = 0;
+
+	if (read_type(&fptr) == false) {
+		free(arg_type);
+		dest_demangle_data(&fptr);
+
+		return (false);
+	}
+
+	rtn_type = vector_str_get_flat(&fptr.vec, &rtn_len);
+	d->p = fptr.p;
+
+
+	dest_demangle_data(&fptr);
+
+	if (vector_str_push(&d->vec, rtn_type, rtn_len) == false) {
+		free(rtn_type);
+		free(arg_type);
+
+		return (false);
+	}
+
+	free(rtn_type);
+
+	if (VEC_PUSH_STR(&d->vec, " (*)(") == false) {
+		free(arg_type);
+
+		return (false);
+	}
+
+	if (vector_str_push(&d->vec, arg_type, arg_len) == false) {
+		free(arg_type);
+
+		return (false);
+	}
+
+	free(arg_type);
+
+	return (VEC_PUSH_STR(&d->vec, ")"));
+}
+
+static bool
+read_memptr(struct demangle_data *d)
+{
+	struct demangle_data mptr;
+	size_t len;
+	bool rtn;
+	char *mptr_str;
+
+	if (d == NULL || d->p == NULL)
+		return (false);
+
+	if (init_demangle_data(&mptr) == false)
+		return (false);
+
+	rtn = false;
+	mptr_str = NULL;
+
+	mptr.p = d->p;
+	if (*mptr.p == 'Q') {
+		++mptr.p;
+
+		if (read_qual_name(&mptr) == false)
+			goto clean;
+	} else {
+		if (read_class(&mptr) == false)
+			goto clean;
+	}
+
+	d->p = mptr.p;
+
+	if ((mptr_str = vector_str_get_flat(&mptr.vec, &len)) == NULL)
+		goto clean;
+
+	if (vector_str_push(&d->vec, mptr_str, len) == false)
+		goto clean;
+
+	if (VEC_PUSH_STR(&d->vec, "::*") == false)
+		goto clean;
+
+	rtn = true;
+clean:
+	free(mptr_str);
+	dest_demangle_data(&mptr);
+
+	return (rtn);
+}
+
+static bool
+read_op(struct demangle_data *d)
+{
+
+	if (d == NULL)
+		return (false);
+
+	assert(d->p != NULL && "d->p (org str) is NULL");
+
+	switch (SIMPLE_HASH(*(d->p), *(d->p+1))) {
+	case SIMPLE_HASH('m', 'l') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator*"));
+	case SIMPLE_HASH('d', 'v') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator/"));
+	case SIMPLE_HASH('m', 'd') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator%"));
+	case SIMPLE_HASH('p', 'l') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator+"));
+	case SIMPLE_HASH('m', 'i') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator-"));
+	case SIMPLE_HASH('l', 's') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator<<"));
+	case SIMPLE_HASH('r', 's') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator>>"));
+	case SIMPLE_HASH('e', 'q') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator=="));
+	case SIMPLE_HASH('n', 'e') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator!="));
+	case SIMPLE_HASH('l', 't') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator<"));
+	case SIMPLE_HASH('g', 't') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator>"));
+	case SIMPLE_HASH('l', 'e') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator<="));
+	case SIMPLE_HASH('g', 'e') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator>="));
+	case SIMPLE_HASH('a', 'd') :
+		d->p += 2;
+		if (*d->p == 'v') {
+			++d->p;
+			return (VEC_PUSH_STR(&d->vec, "operator/="));
+		} else
+			return (VEC_PUSH_STR(&d->vec, "operator&"));
+	case SIMPLE_HASH('o', 'r') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator|"));
+	case SIMPLE_HASH('e', 'r') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator^"));
+	case SIMPLE_HASH('a', 'a') :
+		d->p += 2;
+		if (*d->p == 'd') {
+			++d->p;
+			return (VEC_PUSH_STR(&d->vec, "operator&="));
+		} else
+			return (VEC_PUSH_STR(&d->vec, "operator&&"));
+	case SIMPLE_HASH('o', 'o') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator||"));
+	case SIMPLE_HASH('n', 't') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator!"));
+	case SIMPLE_HASH('c', 'o') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator~"));
+	case SIMPLE_HASH('p', 'p') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator++"));
+	case SIMPLE_HASH('m', 'm') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator--"));
+	case SIMPLE_HASH('a', 's') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator="));
+	case SIMPLE_HASH('r', 'f') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator->"));
+	case SIMPLE_HASH('a', 'p') :
+		/* apl */
+		if (*(d->p + 2) != 'l')
+			return (false);
+
+		d->p += 3;
+		return (VEC_PUSH_STR(&d->vec, "operator+="));
+	case SIMPLE_HASH('a', 'm') :
+		d->p += 2;
+		if (*d->p == 'i') {
+			++d->p;
+			return (VEC_PUSH_STR(&d->vec, "operator-="));
+		} else if (*d->p == 'u') {
+			++d->p;
+			return (VEC_PUSH_STR(&d->vec, "operator*="));
+		} else if (*d->p == 'd') {
+			++d->p;
+			return (VEC_PUSH_STR(&d->vec, "operator%="));
+		}
+
+		return (false);
+	case SIMPLE_HASH('a', 'l') :
+		/* als */
+		if (*(d->p + 2) != 's')
+			return (false);
+
+		d->p += 3;
+		return (VEC_PUSH_STR(&d->vec, "operator<<="));
+	case SIMPLE_HASH('a', 'r') :
+		/* ars */
+		if (*(d->p + 2) != 's')
+			return (false);
+
+		d->p += 3;
+		return (VEC_PUSH_STR(&d->vec, "operator>>="));
+	case SIMPLE_HASH('a', 'o') :
+		/* aor */
+		if (*(d->p + 2) != 'r')
+			return (false);
+
+		d->p += 3;
+		return (VEC_PUSH_STR(&d->vec, "operator|="));
+	case SIMPLE_HASH('a', 'e') :
+		/* aer */
+		if (*(d->p + 2) != 'r')
+			return (false);
+
+		d->p += 3;
+		return (VEC_PUSH_STR(&d->vec, "operator^="));
+	case SIMPLE_HASH('c', 'm') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator,"));
+	case SIMPLE_HASH('r', 'm') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator->*"));
+	case SIMPLE_HASH('c', 'l') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "()"));
+	case SIMPLE_HASH('v', 'c') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "[]"));
+	case SIMPLE_HASH('c', 't') :
+		d->p += 4;
+		d->type = ENCODE_OP_CT;
+
+		if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {
+			++d->p;
+
+			return (read_qual_name(d));
+		} else if (ELFTC_ISDIGIT(*d->p))
+			return (read_class(d));
+
+		return (false);
+	case SIMPLE_HASH('d', 't') :
+		d->p += 4;
+		d->type = ENCODE_OP_DT;
+
+		if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {
+			++d->p;
+
+			return (read_qual_name(d));
+		} else if (ELFTC_ISDIGIT(*d->p))
+			return (read_class(d));
+
+		return (false);
+	case SIMPLE_HASH('n', 'w') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator new()"));
+	case SIMPLE_HASH('d', 'l') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator delete()"));
+	case SIMPLE_HASH('o', 'p') :
+		/* __op<TO_TYPE>__<FROM_TYPE> */
+		d->p += 2;
+
+		d->type = ENCODE_OP_USER;
+
+		return (read_op_user(d));
+	default :
+		return (false);
+	};
+}
+
+static bool
+read_op_user(struct demangle_data *d)
+{
+	struct demangle_data from, to;
+	size_t from_len, to_len;
+	bool rtn;
+	char *from_str, *to_str;
+
+	if (d == NULL)
+		return (false);
+
+	if (init_demangle_data(&from) == false)
+		return (false);
+
+	rtn = false;
+	from_str = NULL;
+	to_str = NULL;
+	if (init_demangle_data(&to) == false)
+		goto clean;
+
+	to.p = d->p;
+	if (*to.p == 'Q') {
+		++to.p;
+
+		if (read_qual_name(&to) == false)
+			goto clean;
+
+		/* pop last '::' */
+		if (vector_str_pop(&to.vec) == false)
+			goto clean;
+	} else {
+		if (read_class(&to) == false)
+			goto clean;
+
+		/* skip '__' */
+		to.p += 2;
+	}
+
+	if ((to_str = vector_str_get_flat(&to.vec, &to_len)) == NULL)
+		goto clean;
+
+	from.p = to.p;
+	if (*from.p == 'Q') {
+		++from.p;
+
+		if (read_qual_name(&from) == false)
+			goto clean;
+
+		/* pop last '::' */
+		if (vector_str_pop(&from.vec) == false)
+			goto clean;
+	} else {
+		if (read_class(&from) == false)
+			goto clean;
+	}
+
+	if ((from_str = vector_str_get_flat(&from.vec, &from_len)) == NULL)
+		goto clean;
+
+	if (vector_str_push(&d->vec, from_str, from_len) == false)
+		goto clean;
+
+	if (VEC_PUSH_STR(&d->vec, "::operator ") == false)
+		return (false);
+
+	if (vector_str_push(&d->vec, to_str, to_len) == false)
+		goto clean;
+
+	rtn = VEC_PUSH_STR(&d->vec, "()");
+clean:
+	free(to_str);
+	free(from_str);
+	dest_demangle_data(&to);
+	dest_demangle_data(&from);
+
+	return (rtn);
+}
+
+/* single digit + class names */
+static bool
+read_qual_name(struct demangle_data *d)
+{
+	int i;
+	char num;
+
+	if (d == NULL)
+		return (false);
+
+	assert(d->p != NULL && "d->p (org str) is NULL");
+	assert(*d->p > 48 && *d->p < 58 && "*d->p not in ASCII numeric range");
+
+	num = *d->p - 48;
+
+	assert(num > 0);
+
+	++d->p;
+	for (i = 0; i < num ; ++i) {
+		if (read_class(d) == false)
+			return (false);
+
+		if (VEC_PUSH_STR(&d->vec, "::") == false)
+			return (false);
+	}
+
+	if (*d->p != '\0')
+		d->p = d->p + 2;
+
+	return (true);
+}
+
+/* Return -1 at fail, 0 at success, and 1 at end */
+static int
+read_subst(struct demangle_data *d)
+{
+	size_t idx;
+	char *str;
+
+	if (d == NULL)
+		return (-1);
+
+	idx = strtol(d->p + 1, &str, 10);
+	if (idx == 0 && (errno == EINVAL || errno == ERANGE))
+		return (-1);
+
+	assert(idx > 0);
+	assert(str != NULL);
+
+	d->p = str;
+
+	if (VEC_PUSH_STR(&d->vec, d->arg.container[idx - 1]) == false)
+		return (-1);
+
+	if (VEC_PUSH_STR(&d->arg, d->arg.container[idx - 1]) == false)
+		return (-1);
+
+	if (*d->p == '\0')
+		return (1);
+
+	return (0);
+}
+
+static int
+read_subst_iter(struct demangle_data *d)
+{
+	int i;
+	size_t idx;
+	char repeat;
+	char *str;
+
+	if (d == NULL)
+		return (-1);
+
+	++d->p;
+	assert(*d->p > 48 && *d->p < 58 && "*d->p not in ASCII numeric range");
+
+	repeat = *d->p - 48;
+
+	assert(repeat > 1);
+
+	++d->p;
+
+	idx = strtol(d->p, &str, 10);
+	if (idx == 0 && (errno == EINVAL || errno == ERANGE))
+		return (-1);
+
+	assert(idx > 0);
+	assert(str != NULL);
+
+	d->p = str;
+
+	for (i = 0; i < repeat ; ++i) {
+		if (VEC_PUSH_STR(&d->vec, d->arg.container[idx - 1]) == false)
+			return (-1);
+
+		if (VEC_PUSH_STR(&d->arg, d->arg.container[idx - 1]) == false)
+			return (-1);
+
+		if (i != repeat - 1 &&
+		    VEC_PUSH_STR(&d->vec, ", ") == false)
+			return (-1);
+	}
+
+	if (*d->p == '\0')
+		return (1);
+
+	return (0);
+}
+
+static bool
+read_type(struct demangle_data *d)
+{
+
+	if (d == NULL)
+		return (false);
+
+	assert(d->p != NULL && "d->p (org str) is NULL");
+
+	while (*d->p == 'U' || *d->p == 'C' || *d->p == 'V' || *d->p == 'S' ||
+	       *d->p == 'P' || *d->p == 'R' || *d->p == 'A' || *d->p == 'F' ||
+	       *d->p == 'M') {
+		switch (*d->p) {
+		case 'U' :
+			++d->p;
+
+			if (VEC_PUSH_STR(&d->vec, "unsigned ") == false)
+				return (false);
+
+			break;
+		case 'C' :
+			++d->p;
+
+			if (*d->p == 'P')
+				d->cnst = true;
+			else {
+				if (VEC_PUSH_STR(&d->vec, "const ") ==
+				    false)
+					return (false);
+			}
+
+			break;
+		case 'V' :
+			++d->p;
+
+			if (VEC_PUSH_STR(&d->vec, "volatile ") == false)
+				return (false);
+
+			break;
+		case 'S' :
+			++d->p;
+
+			if (VEC_PUSH_STR(&d->vec, "signed ") == false)
+				return (false);
+
+			break;
+		case 'P' :
+			++d->p;
+
+			if (*d->p == 'F')
+				return (read_func_ptr(d));
+			else
+				d->ptr = true;
+
+			break;
+		case 'R' :
+			++d->p;
+
+			d->ref = true;
+
+			break;
+		case 'F' :
+			break;
+		case 'A' :
+			++d->p;
+
+			if (read_array(d) == false)
+				return (false);
+
+			break;
+		case 'M' :
+			++d->p;
+
+			if (read_memptr(d) == false)
+				return (false);
+
+			break;
+		default :
+			break;
+		}
+	}
+
+	if (ELFTC_ISDIGIT(*d->p))
+		return (read_class(d));
+
+	switch (*d->p) {
+	case 'Q' :
+		++d->p;
+
+		return (read_qual_name(d));
+	case 'v' :
+		++d->p;
+
+		return (VEC_PUSH_STR(&d->vec, "void"));
+	case 'c' :
+		++d->p;
+
+		return (VEC_PUSH_STR(&d->vec, "char"));
+	case 's' :
+		++d->p;
+
+		return (VEC_PUSH_STR(&d->vec, "short"));
+	case 'i' :
+		++d->p;
+
+		return (VEC_PUSH_STR(&d->vec, "int"));
+	case 'l' :
+		++d->p;
+
+		return (VEC_PUSH_STR(&d->vec, "long"));
+	case 'f' :
+		++d->p;
+
+		return (VEC_PUSH_STR(&d->vec, "float"));
+	case 'd':
+		++d->p;
+
+		return (VEC_PUSH_STR(&d->vec, "double"));
+	case 'r':
+		++d->p;
+
+		return (VEC_PUSH_STR(&d->vec, "long double"));
+	case 'e':
+		++d->p;
+
+		return (VEC_PUSH_STR(&d->vec, "..."));
+	default:
+		return (false);
+	};
+
+	/* NOTREACHED */
+	return (false);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/libelftc_dem_gnu2.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,1365 @@
+/*-
+ * Copyright (c) 2008 Hyogeol Lee <hyogeollee@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <libelftc.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "_libelftc.h"
+
+ELFTC_VCSID("$Id: libelftc_dem_gnu2.c 3513 2016-12-29 07:04:22Z kaiwang27 $");
+
+/**
+ * @file cpp_demangle_gnu2.c
+ * @brief Decode function name encoding in GNU 2.
+ *
+ * Function name encoding in GNU 2 based on ARM style.
+ */
+
+enum encode_type {
+	ENCODE_FUNC, ENCODE_OP, ENCODE_OP_CT, ENCODE_OP_DT, ENCODE_OP_USER,
+	ENCODE_OP_TF, ENCODE_OP_TI, ENCODE_OP_VT
+};
+
+struct cstring {
+	char	*buf;
+	size_t	size;
+};
+
+struct demangle_data {
+	bool	ptr, ref, cnst, array, cnst_fn, class_name;
+	struct cstring array_str;
+	const char *p;
+	enum encode_type type;
+	struct vector_str vec;
+	struct vector_str arg;
+};
+
+#define SIMPLE_HASH(x,y)	(64 * x + y)
+#define VEC_PUSH_STR(d,s)	vector_str_push((d), (s), strlen((s)))
+#define	CPP_DEMANGLE_GNU2_TRY	128
+
+static void	dest_cstring(struct cstring *);
+static void	dest_demangle_data(struct demangle_data *);
+static bool	init_cstring(struct cstring *, size_t);
+static bool	init_demangle_data(struct demangle_data *);
+static bool	push_CTDT(const char *, size_t, struct vector_str *);
+static bool	read_array(struct demangle_data *);
+static bool	read_class(struct demangle_data *);
+static bool	read_func(struct demangle_data *);
+static bool	read_func_name(struct demangle_data *);
+static bool	read_func_ptr(struct demangle_data *);
+static bool	read_memptr(struct demangle_data *);
+static bool	read_op(struct demangle_data *);
+static bool	read_op_user(struct demangle_data *);
+static bool	read_qual_name(struct demangle_data *);
+static int	read_subst(struct demangle_data *);
+static int	read_subst_iter(struct demangle_data *);
+static bool	read_type(struct demangle_data *);
+
+/**
+ * @brief Decode the input string by the GNU 2 style.
+ *
+ * @return New allocated demangled string or NULL if failed.
+ */
+char *
+cpp_demangle_gnu2(const char *org)
+{
+	struct demangle_data d;
+	size_t arg_begin, arg_len;
+	unsigned int try;
+	char *rtn, *arg;
+
+	if (org == NULL)
+		return (NULL);
+
+	if (init_demangle_data(&d) == false)
+		return (NULL);
+
+	try = 0;
+	rtn = NULL;
+
+	d.p = org;
+	if (read_func_name(&d) == false)
+		goto clean;
+
+	switch (d.type) {
+	case ENCODE_FUNC :
+	case ENCODE_OP :
+		break;
+
+	case ENCODE_OP_CT :
+		if (push_CTDT("::", 2, &d.vec) == false)
+			goto clean;
+
+                break;
+	case ENCODE_OP_DT :
+		if (push_CTDT("::~", 3, &d.vec) == false)
+			goto clean;
+
+		if (VEC_PUSH_STR(&d.vec, "(void)") == false)
+			goto clean;
+
+		goto flat;
+	case ENCODE_OP_USER :
+	case ENCODE_OP_TF :
+	case ENCODE_OP_TI :
+	case ENCODE_OP_VT :
+		goto flat;
+	}
+
+	if (*d.p == 'F')
+		++d.p;
+	else if (*d.p == '\0') {
+		if (d.class_name == true) {
+			if (VEC_PUSH_STR(&d.vec, "(void)") == false)
+				goto clean;
+
+			goto flat;
+		} else
+			goto clean;
+	}
+
+	/* start argument types */
+	if (VEC_PUSH_STR(&d.vec, "(") == false)
+		goto clean;
+
+	for (;;) {
+		if (*d.p == 'T') {
+			const int rtn_subst = read_subst(&d);
+
+			if (rtn_subst == -1)
+				goto clean;
+			else if (rtn_subst == 1)
+				break;
+
+			continue;
+		}
+
+		if (*d.p == 'N') {
+			const int rtn_subst_iter = read_subst_iter(&d);
+
+			if (rtn_subst_iter == -1)
+				goto clean;
+			else if(rtn_subst_iter == 1)
+				break;
+
+			continue;
+		}
+
+		arg_begin = d.vec.size;
+
+		if (read_type(&d) == false)
+			goto clean;
+
+		if (d.ptr == true) {
+			if (VEC_PUSH_STR(&d.vec, "*") == false)
+				goto clean;
+
+			d.ptr = false;
+		}
+
+		if (d.ref == true) {
+			if (VEC_PUSH_STR(&d.vec, "&") == false)
+				goto clean;
+
+			d.ref = false;
+		}
+
+		if (d.cnst == true) {
+			if (VEC_PUSH_STR(&d.vec, " const") == false)
+				goto clean;
+
+			d.cnst = false;
+		}
+
+		if (d.array == true) {
+			if (vector_str_push(&d.vec, d.array_str.buf,
+				d.array_str.size) == false)
+				goto clean;
+
+			dest_cstring(&d.array_str);
+			d.array = false;
+		}
+
+		if (*d.p == '\0')
+			break;
+
+		if ((arg = vector_str_substr(&d.vec, arg_begin, d.vec.size - 1,
+			    &arg_len)) == NULL)
+			goto clean;
+
+		if (vector_str_push(&d.arg, arg, arg_len) == false)
+			goto clean;
+
+		free(arg);
+
+		if (VEC_PUSH_STR(&d.vec, ", ") == false)
+			goto clean;
+
+		if (++try > CPP_DEMANGLE_GNU2_TRY)
+			goto clean;
+	}
+
+	/* end argument types */
+	if (VEC_PUSH_STR(&d.vec, ")") == false)
+		goto clean;
+flat:
+	if (d.cnst_fn == true && VEC_PUSH_STR(&d.vec, " const") == false)
+		goto clean;
+
+	rtn = vector_str_get_flat(&d.vec, NULL);
+clean:
+	dest_demangle_data(&d);
+
+	return (rtn);
+}
+
+/**
+ * @brief Test input string is encoded by the GNU 2 style.
+ *
+ * @return True if input string is encoded by the GNU 2 style.
+ */
+bool
+is_cpp_mangled_gnu2(const char *org)
+{
+	char *str;
+	bool rtn = false;
+
+	if (org == NULL)
+		return (false);
+
+	/* search valid text to end */
+	str = strstr(org, "__");
+	while (str != NULL) {
+		if (*(str + 2) != '\0') {
+			if (*(str + 2) == 'C' ||
+			    *(str + 2) == 'F' ||
+			    *(str + 2) == 'Q' ||
+			    ELFTC_ISDIGIT(*(str + 2))) {
+				rtn |= true;
+				
+				break;
+			}
+			
+			if (*(str + 3) != '\0') {
+				switch (SIMPLE_HASH(*(str + 2), *(str + 3))) {
+				case SIMPLE_HASH('m', 'l') :
+				case SIMPLE_HASH('d', 'v') :
+				case SIMPLE_HASH('m', 'd') :
+				case SIMPLE_HASH('p', 'l') :
+				case SIMPLE_HASH('m', 'i') :
+				case SIMPLE_HASH('l', 's') :
+				case SIMPLE_HASH('r', 's') :
+				case SIMPLE_HASH('e', 'q') :
+				case SIMPLE_HASH('n', 'e') :
+				case SIMPLE_HASH('l', 't') :
+				case SIMPLE_HASH('g', 't') :
+				case SIMPLE_HASH('l', 'e') :
+				case SIMPLE_HASH('g', 'e') :
+				case SIMPLE_HASH('a', 'd') :
+				case SIMPLE_HASH('o', 'r') :
+				case SIMPLE_HASH('e', 'r') :
+				case SIMPLE_HASH('a', 'a') :
+				case SIMPLE_HASH('o', 'o') :
+				case SIMPLE_HASH('n', 't') :
+				case SIMPLE_HASH('c', 'o') :
+				case SIMPLE_HASH('p', 'p') :
+				case SIMPLE_HASH('m', 'm') :
+				case SIMPLE_HASH('a', 's') :
+				case SIMPLE_HASH('r', 'f') :
+				case SIMPLE_HASH('a', 'p') :
+				case SIMPLE_HASH('a', 'm') :
+				case SIMPLE_HASH('a', 'l') :
+				case SIMPLE_HASH('a', 'r') :
+				case SIMPLE_HASH('a', 'o') :
+				case SIMPLE_HASH('a', 'e') :
+				case SIMPLE_HASH('c', 'm') :
+				case SIMPLE_HASH('r', 'm') :
+				case SIMPLE_HASH('c', 'l') :
+				case SIMPLE_HASH('v', 'c') :
+				case SIMPLE_HASH('n', 'w') :
+				case SIMPLE_HASH('d', 'l') :
+				case SIMPLE_HASH('o', 'p') :
+				case SIMPLE_HASH('t', 'f') :
+				case SIMPLE_HASH('t', 'i') :
+					rtn |= true;
+
+					break;
+				}
+			}
+		}
+
+		str = strstr(str + 2, "__");
+	}
+
+	rtn |= strstr(org, "_$_") != NULL;
+	rtn |= strstr(org, "_vt$") != NULL;
+
+	return (rtn);
+}
+
+static void
+dest_cstring(struct cstring *s)
+{
+
+	if (s == NULL)
+		return;
+
+	free(s->buf);
+	s->buf = NULL;
+	s->size = 0;
+}
+
+static void
+dest_demangle_data(struct demangle_data *d)
+{
+
+	if (d != NULL) {
+		vector_str_dest(&d->arg);
+		vector_str_dest(&d->vec);
+
+		dest_cstring(&d->array_str);
+	}
+}
+
+static bool
+init_cstring(struct cstring *s, size_t len)
+{
+
+	if (s == NULL || len <= 1)
+		return (false);
+
+	if ((s->buf = malloc(sizeof(char) * len)) == NULL)
+		return (false);
+
+	s->size = len - 1;
+
+	return (true);
+}
+
+static bool
+init_demangle_data(struct demangle_data *d)
+{
+
+	if (d == NULL)
+		return (false);
+
+	d->ptr = false;
+	d->ref = false;
+	d->cnst = false;
+	d->array = false;
+	d->cnst_fn = false;
+	d->class_name = false;
+
+	d->array_str.buf = NULL;
+	d->array_str.size = 0;
+
+	d->type = ENCODE_FUNC;
+
+	if (vector_str_init(&d->vec) == false)
+		return (false);
+
+	if (vector_str_init(&d->arg) == false) {
+		vector_str_dest(&d->vec);
+
+		return (false);
+	}
+
+	return (true);
+}
+
+static bool
+push_CTDT(const char *s, size_t l, struct vector_str *v)
+{
+
+	if (s == NULL || l == 0 || v == NULL)
+		return (false);
+
+	if (vector_str_push(v, s, l) == false)
+		return (false);
+
+	assert(v->size > 1);
+
+	return (VEC_PUSH_STR(v, v->container[v->size - 2]));
+}
+
+static bool
+read_array(struct demangle_data *d)
+{
+	size_t len;
+	const char *end;
+
+	if (d == NULL || d->p == NULL)
+		return (false);
+
+	end = d->p;
+	assert(end != NULL);
+
+	for (;;) {
+		if (*end == '\0')
+			return (false);
+
+		if (ELFTC_ISDIGIT(*end) == 0)
+			break;
+
+		++end;
+	}
+
+	if (*end != '_')
+		return (false);
+
+	len = end - d->p;
+	assert(len > 0);
+
+	dest_cstring(&d->array_str);
+	if (init_cstring(&d->array_str, len + 3) == false)
+		return (false);
+
+	strncpy(d->array_str.buf + 1, d->p, len);
+	*d->array_str.buf = '[';
+	*(d->array_str.buf + len + 1) = ']';
+
+	d->array = true;
+	d->p = end + 1;
+
+	return (true);
+}
+
+static bool
+read_class(struct demangle_data *d)
+{
+	size_t len;
+	char *str;
+
+	if (d == NULL)
+		return (false);
+
+	len = strtol(d->p, &str, 10);
+	if (len == 0 && (errno == EINVAL || errno == ERANGE))
+		return (false);
+
+	assert(len > 0);
+	assert(str != NULL);
+
+	if (vector_str_push(&d->vec, str, len) == false)
+		return (false);
+
+	d->p = str + len;
+
+	d->class_name = true;
+
+	return (true);
+}
+
+static bool
+read_func(struct demangle_data *d)
+{
+	size_t len;
+	const char *name;
+	char *delim;
+
+	if (d == NULL)
+		return (false);
+
+	assert(d->p != NULL && "d->p (org str) is NULL");
+	if ((delim = strstr(d->p, "__")) == NULL)
+		return (false);
+
+	len = delim - d->p;
+	assert(len != 0);
+
+	name = d->p;
+
+	d->p = delim + 2;
+
+	if (*d->p == 'C') {
+		++d->p;
+
+		d->cnst_fn = true;
+	}
+
+	if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {
+		++d->p;
+
+		if (read_qual_name(d) == false)
+			return (false);
+	} else if (ELFTC_ISDIGIT(*d->p)) {
+		if (read_class(d) == false)
+			return (false);
+
+		if (VEC_PUSH_STR(&d->vec, "::") == false)
+			return (false);
+	}
+
+	return (vector_str_push(&d->vec, name, len));
+}
+
+static bool
+read_func_name(struct demangle_data *d)
+{
+	size_t len;
+	bool rtn;
+	char *op_name;
+
+	if (d == NULL)
+		return (false);
+
+	rtn = false;
+	op_name = NULL;
+
+	assert(d->p != NULL && "d->p (org str) is NULL");
+
+	if (*d->p == '_' && *(d->p + 1) == '_') {
+		d->p += 2;
+
+		/* CTOR */
+		if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {
+			++d->p;
+			d->type = ENCODE_OP_CT;
+
+			if (read_qual_name(d) == false)
+				return (false);
+
+			return (vector_str_pop(&d->vec));
+		} else if (ELFTC_ISDIGIT(*d->p)) {
+			d->type = ENCODE_OP_CT;
+
+			return (read_class(d));
+		}
+
+		d->type = ENCODE_OP;
+		if (read_op(d) == false) {
+			/* not good condition, start function name with '__' */
+			d->type = ENCODE_FUNC;
+
+			if (VEC_PUSH_STR(&d->vec, "__") == false)
+				return (false);
+			
+			return (read_func(d));
+		}
+
+		if (d->type == ENCODE_OP_USER ||
+		    d->type == ENCODE_OP_TF ||
+		    d->type == ENCODE_OP_TI)
+			return (true);
+
+		/* skip "__" */
+		d->p += 2;
+
+		if (*d->p == 'C') {
+			++d->p;
+
+			d->cnst_fn = true;
+		}
+
+		/* assume delimiter is removed */
+		if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {
+			++d->p;
+
+			assert(d->vec.size > 0);
+
+			len = strlen(d->vec.container[d->vec.size - 1]);
+			if ((op_name = malloc(sizeof(char) * (len + 1)))
+			    == NULL)
+				return (false);
+
+			snprintf(op_name, len + 1, "%s",
+			    d->vec.container[d->vec.size - 1]);
+			vector_str_pop(&d->vec);
+
+			if (read_qual_name(d) == false)
+				goto clean;
+
+			if (VEC_PUSH_STR(&d->vec, "::") == false)
+				goto clean;
+
+			if (vector_str_push(&d->vec, op_name, len) == false)
+				goto clean;
+
+			rtn = true;
+		} else if (ELFTC_ISDIGIT(*d->p)) {
+			assert(d->vec.size > 0);
+
+			len = strlen(d->vec.container[d->vec.size - 1]);
+			if ((op_name = malloc(sizeof(char) * (len + 1)))
+			    == NULL)
+				return (false);
+
+			snprintf(op_name, len + 1, "%s",
+			    d->vec.container[d->vec.size - 1]);
+			vector_str_pop(&d->vec);
+
+			if (read_class(d) == false)
+				goto clean;
+
+			if (VEC_PUSH_STR(&d->vec, "::") == false)
+				goto clean;
+
+			if (vector_str_push(&d->vec, op_name, len) == false)
+				goto clean;
+
+			rtn = true;
+		}
+	} else if (memcmp(d->p, "_$_", 3) == 0) {
+		/* DTOR */
+		d->p += 3;
+		d->type = ENCODE_OP_DT;
+
+		if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {
+			++d->p;
+
+			if (read_qual_name(d) == false)
+				return (false);
+
+			return (vector_str_pop(&d->vec));
+		} else if (ELFTC_ISDIGIT(*d->p))
+			return (read_class(d));
+
+		return (false);
+	} else if (memcmp(d->p, "_vt$", 4) == 0) {
+		/* vtable */
+		d->p += 4;
+		d->type = ENCODE_OP_VT;
+
+		if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {
+			++d->p;
+
+			if (read_qual_name(d) == false)
+				return (false);
+
+			if (vector_str_pop(&d->vec) == false)
+				return (false);
+		} else if (ELFTC_ISDIGIT(*d->p)) {
+			if (read_class(d) == false)
+				return (false);
+		}
+
+		return (VEC_PUSH_STR(&d->vec, " virtual table"));
+	} else
+		return (read_func(d));
+clean:
+	free(op_name);
+
+	return (rtn);
+}
+
+/* Read function ptr type */
+static bool
+read_func_ptr(struct demangle_data *d)
+{
+	struct demangle_data fptr;
+	size_t arg_len, rtn_len;
+	char *arg_type, *rtn_type;
+	int lim;
+
+	if (d == NULL)
+		return (false);
+
+	if (init_demangle_data(&fptr) == false)
+		return (false);
+
+	fptr.p = d->p + 1;
+	lim = 0;
+	arg_type = NULL;
+	rtn_type = NULL;
+
+	for (;;) {
+		if (read_type(&fptr) == false) {
+			dest_demangle_data(&fptr);
+
+			return (false);
+		}
+
+		if (fptr.ptr == true) {
+			if (VEC_PUSH_STR(&fptr.vec, "*") == false) {
+				dest_demangle_data(&fptr);
+
+				return (false);
+			}
+
+			fptr.ptr = false;
+		}
+
+		if (fptr.ref == true) {
+			if (VEC_PUSH_STR(&fptr.vec, "&") == false) {
+				dest_demangle_data(&fptr);
+
+				return (false);
+			}
+
+			fptr.ref = false;
+		}
+
+		if (fptr.cnst == true) {
+			if (VEC_PUSH_STR(&fptr.vec, " const") == false) {
+				dest_demangle_data(&fptr);
+
+				return (false);
+			}
+
+			fptr.cnst = false;
+		}
+
+		if (*fptr.p == '_')
+			break;
+
+		if (VEC_PUSH_STR(&fptr.vec, ", ") == false) {
+			dest_demangle_data(&fptr);
+
+			return (false);
+		}
+
+		if (++lim > CPP_DEMANGLE_GNU2_TRY) {
+
+			dest_demangle_data(&fptr);
+
+			return (false);
+		}
+	}
+
+	arg_type = vector_str_get_flat(&fptr.vec, &arg_len);
+	/* skip '_' */
+	d->p = fptr.p + 1;
+
+	dest_demangle_data(&fptr);
+
+	if (init_demangle_data(&fptr) == false) {
+		free(arg_type);
+
+		return (false);
+	}
+
+	fptr.p = d->p;
+	lim = 0;
+
+	if (read_type(&fptr) == false) {
+		free(arg_type);
+		dest_demangle_data(&fptr);
+
+		return (false);
+	}
+
+	rtn_type = vector_str_get_flat(&fptr.vec, &rtn_len);
+	d->p = fptr.p;
+
+
+	dest_demangle_data(&fptr);
+
+	if (vector_str_push(&d->vec, rtn_type, rtn_len) == false) {
+		free(rtn_type);
+		free(arg_type);
+
+		return (false);
+	}
+
+	free(rtn_type);
+
+	if (VEC_PUSH_STR(&d->vec, " (*)(") == false) {
+		free(arg_type);
+
+		return (false);
+	}
+
+	if (vector_str_push(&d->vec, arg_type, arg_len) == false) {
+		free(arg_type);
+
+		return (false);
+	}
+
+	free(arg_type);
+
+	return (VEC_PUSH_STR(&d->vec, ")"));
+}
+
+static bool
+read_memptr(struct demangle_data *d)
+{
+	struct demangle_data mptr;
+	size_t len;
+	bool rtn;
+	char *mptr_str;
+
+	if (d == NULL || d->p == NULL)
+		return (false);
+
+	if (init_demangle_data(&mptr) == false)
+		return (false);
+
+	rtn = false;
+	mptr_str = NULL;
+
+	mptr.p = d->p;
+	if (*mptr.p == 'Q') {
+		++mptr.p;
+
+		if (read_qual_name(&mptr) == false)
+			goto clean;
+	} else if (read_class(&mptr) == false)
+			goto clean;
+
+	d->p = mptr.p;
+
+	if ((mptr_str = vector_str_get_flat(&mptr.vec, &len)) == NULL)
+		goto clean;
+
+	if (vector_str_push(&d->vec, mptr_str, len) == false)
+		goto clean;
+
+	if (VEC_PUSH_STR(&d->vec, "::*") == false)
+		goto clean;
+
+	rtn = true;
+clean:
+	free(mptr_str);
+	dest_demangle_data(&mptr);
+
+	return (rtn);
+}
+
+static bool
+read_op(struct demangle_data *d)
+{
+
+	if (d == NULL)
+		return (false);
+
+	assert(d->p != NULL && "d->p (org str) is NULL");
+
+	switch (SIMPLE_HASH(*(d->p), *(d->p+1))) {
+	case SIMPLE_HASH('m', 'l') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator*"));
+	case SIMPLE_HASH('d', 'v') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator/"));
+	case SIMPLE_HASH('m', 'd') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator%"));
+	case SIMPLE_HASH('p', 'l') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator+"));
+	case SIMPLE_HASH('m', 'i') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator-"));
+	case SIMPLE_HASH('l', 's') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator<<"));
+	case SIMPLE_HASH('r', 's') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator>>"));
+	case SIMPLE_HASH('e', 'q') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator=="));
+	case SIMPLE_HASH('n', 'e') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator!="));
+	case SIMPLE_HASH('l', 't') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator<"));
+	case SIMPLE_HASH('g', 't') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator>"));
+	case SIMPLE_HASH('l', 'e') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator<="));
+	case SIMPLE_HASH('g', 'e') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator>="));
+	case SIMPLE_HASH('a', 'd') :
+		d->p += 2;
+		if (*d->p == 'v') {
+			++d->p;
+			return (VEC_PUSH_STR(&d->vec, "operator/="));
+		} else
+			return (VEC_PUSH_STR(&d->vec, "operator&"));
+	case SIMPLE_HASH('o', 'r') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator|"));
+	case SIMPLE_HASH('e', 'r') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator^"));
+	case SIMPLE_HASH('a', 'a') :
+		d->p += 2;
+		if (*d->p == 'd') {
+			++d->p;
+			return (VEC_PUSH_STR(&d->vec, "operator&="));
+		} else
+			return (VEC_PUSH_STR(&d->vec, "operator&&"));
+	case SIMPLE_HASH('o', 'o') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator||"));
+	case SIMPLE_HASH('n', 't') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator!"));
+	case SIMPLE_HASH('c', 'o') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator~"));
+	case SIMPLE_HASH('p', 'p') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator++"));
+	case SIMPLE_HASH('m', 'm') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator--"));
+	case SIMPLE_HASH('a', 's') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator="));
+	case SIMPLE_HASH('r', 'f') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator->"));
+	case SIMPLE_HASH('a', 'p') :
+		/* apl */
+		if (*(d->p + 2) != 'l')
+			return (false);
+
+		d->p += 3;
+		return (VEC_PUSH_STR(&d->vec, "operator+="));
+	case SIMPLE_HASH('a', 'm') :
+		d->p += 2;
+		if (*d->p == 'i') {
+			++d->p;
+			return (VEC_PUSH_STR(&d->vec, "operator-="));
+		} else if (*d->p == 'u') {
+			++d->p;
+			return (VEC_PUSH_STR(&d->vec, "operator*="));
+		} else if (*d->p == 'd') {
+			++d->p;
+			return (VEC_PUSH_STR(&d->vec, "operator%="));
+		}
+
+		return (false);
+	case SIMPLE_HASH('a', 'l') :
+		/* als */
+		if (*(d->p + 2) != 's')
+			return (false);
+
+		d->p += 3;
+		return (VEC_PUSH_STR(&d->vec, "operator<<="));
+	case SIMPLE_HASH('a', 'r') :
+		/* ars */
+		if (*(d->p + 2) != 's')
+			return (false);
+
+		d->p += 3;
+		return (VEC_PUSH_STR(&d->vec, "operator>>="));
+	case SIMPLE_HASH('a', 'o') :
+		/* aor */
+		if (*(d->p + 2) != 'r')
+			return (false);
+
+		d->p += 3;
+		return (VEC_PUSH_STR(&d->vec, "operator|="));
+	case SIMPLE_HASH('a', 'e') :
+		/* aer */
+		if (*(d->p + 2) != 'r')
+			return (false);
+
+		d->p += 3;
+		return (VEC_PUSH_STR(&d->vec, "operator^="));
+	case SIMPLE_HASH('c', 'm') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator,"));
+	case SIMPLE_HASH('r', 'm') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator->*"));
+	case SIMPLE_HASH('c', 'l') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "()"));
+	case SIMPLE_HASH('v', 'c') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "[]"));
+	case SIMPLE_HASH('n', 'w') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator new()"));
+	case SIMPLE_HASH('d', 'l') :
+		d->p += 2;
+		return (VEC_PUSH_STR(&d->vec, "operator delete()"));
+	case SIMPLE_HASH('o', 'p') :
+		/* __op<TO_TYPE>__<FROM_TYPE> */
+		d->p += 2;
+
+		d->type = ENCODE_OP_USER;
+
+		return (read_op_user(d));
+	case SIMPLE_HASH('t', 'f') :
+		d->p += 2;
+		d->type = ENCODE_OP_TF;
+
+		if (read_type(d) == false)
+			return (false);
+
+		return (VEC_PUSH_STR(&d->vec, " type_info function"));
+	case SIMPLE_HASH('t', 'i') :
+		d->p += 2;
+		d->type = ENCODE_OP_TI;
+
+		if (read_type(d) == false)
+			return (false);
+
+		return (VEC_PUSH_STR(&d->vec, " type_info node"));
+	default :
+		return (false);
+	};
+}
+
+static bool
+read_op_user(struct demangle_data *d)
+{
+	struct demangle_data from, to;
+	size_t from_len, to_len;
+	bool rtn;
+	char *from_str, *to_str;
+
+	if (d == NULL)
+		return (false);
+
+	if (init_demangle_data(&from) == false)
+		return (false);
+
+	rtn = false;
+	from_str = NULL;
+	to_str = NULL;
+	if (init_demangle_data(&to) == false)
+		goto clean;
+
+	to.p = d->p;
+	if (*to.p == 'Q') {
+		++to.p;
+
+		if (read_qual_name(&to) == false)
+			goto clean;
+
+		/* pop last '::' */
+		if (vector_str_pop(&to.vec) == false)
+			goto clean;
+	} else {
+		if (read_class(&to) == false)
+			goto clean;
+
+		/* skip '__' */
+		to.p += 2;
+	}
+
+	if ((to_str = vector_str_get_flat(&to.vec, &to_len)) == NULL)
+		goto clean;
+
+	from.p = to.p;
+	if (*from.p == 'Q') {
+		++from.p;
+
+		if (read_qual_name(&from) == false)
+			goto clean;
+
+		/* pop last '::' */
+		if (vector_str_pop(&from.vec) == false)
+			goto clean;
+	} else if (read_class(&from) == false)
+			goto clean;
+
+	if ((from_str = vector_str_get_flat(&from.vec, &from_len)) == NULL)
+		goto clean;
+
+	if (vector_str_push(&d->vec, from_str, from_len) == false)
+		goto clean;
+
+	if (VEC_PUSH_STR(&d->vec, "::operator ") == false)
+		goto clean;
+
+	if (vector_str_push(&d->vec, to_str, to_len) == false)
+		goto clean;
+
+	rtn = VEC_PUSH_STR(&d->vec, "()");
+clean:
+	free(to_str);
+	free(from_str);
+	dest_demangle_data(&to);
+	dest_demangle_data(&from);
+
+	return (rtn);
+}
+
+/* single digit + class names */
+static bool
+read_qual_name(struct demangle_data *d)
+{
+	int i;
+	char num;
+
+	if (d == NULL)
+		return (false);
+
+	assert(d->p != NULL && "d->p (org str) is NULL");
+	assert(*d->p > 48 && *d->p < 58 && "*d->p not in ASCII numeric range");
+
+	num = *d->p - 48;
+
+	assert(num > 0);
+
+	++d->p;
+	for (i = 0; i < num ; ++i) {
+		if (read_class(d) == false)
+			return (false);
+
+		if (VEC_PUSH_STR(&d->vec, "::") == false)
+			return (false);
+	}
+
+	if (*d->p != '\0')
+		d->p = d->p + 2;
+
+	return (true);
+}
+
+/* Return -1 at fail, 0 at success, and 1 at end */
+static int
+read_subst(struct demangle_data *d)
+{
+	size_t idx;
+	char *str;
+
+	if (d == NULL)
+		return (-1);
+
+	idx = strtol(d->p + 1, &str, 10);
+	if (idx == 0 && (errno == EINVAL || errno == ERANGE))
+		return (-1);
+
+	assert(idx > 0);
+	assert(str != NULL);
+
+	d->p = str;
+
+	if (VEC_PUSH_STR(&d->vec, d->arg.container[idx - 1]) == false)
+		return (-1);
+
+	if (VEC_PUSH_STR(&d->arg, d->arg.container[idx - 1]) == false)
+		return (-1);
+
+	if (*d->p == '\0')
+		return (1);
+
+	return (0);
+}
+
+static int
+read_subst_iter(struct demangle_data *d)
+{
+	int i;
+	size_t idx;
+	char repeat;
+	char *str;
+
+	if (d == NULL)
+		return (-1);
+
+	++d->p;
+	assert(*d->p > 48 && *d->p < 58 && "*d->p not in ASCII numeric range");
+
+	repeat = *d->p - 48;
+
+	assert(repeat > 1);
+
+	++d->p;
+
+	idx = strtol(d->p, &str, 10);
+	if (idx == 0 && (errno == EINVAL || errno == ERANGE))
+		return (-1);
+
+	assert(idx > 0);
+	assert(str != NULL);
+
+	d->p = str;
+
+	for (i = 0; i < repeat ; ++i) {
+		if (VEC_PUSH_STR(&d->vec, d->arg.container[idx - 1]) == false)
+			return (-1);
+
+		if (VEC_PUSH_STR(&d->arg, d->arg.container[idx - 1]) == false)
+			return (-1);
+
+		if (i != repeat - 1 &&
+		    VEC_PUSH_STR(&d->vec, ", ") == false)
+			return (-1);
+	}
+
+	if (*d->p == '\0')
+		return (1);
+
+	return (0);
+}
+
+static bool
+read_type(struct demangle_data *d)
+{
+
+	if (d == NULL)
+		return (false);
+
+	assert(d->p != NULL && "d->p (org str) is NULL");
+
+	while (*d->p == 'U' || *d->p == 'C' || *d->p == 'V' || *d->p == 'S' ||
+	       *d->p == 'P' || *d->p == 'R' || *d->p == 'A' || *d->p == 'F' ||
+	       *d->p == 'M') {
+		switch (*d->p) {
+		case 'U' :
+			++d->p;
+
+			if (VEC_PUSH_STR(&d->vec, "unsigned ") == false)
+				return (false);
+
+			break;
+		case 'C' :
+			++d->p;
+
+			if (*d->p == 'P')
+				d->cnst = true;
+			else {
+				if (VEC_PUSH_STR(&d->vec, "const ") ==
+				    false)
+					return (false);
+			}
+
+			break;
+		case 'V' :
+			++d->p;
+
+			if (VEC_PUSH_STR(&d->vec, "volatile ") == false)
+				return (false);
+
+			break;
+		case 'S' :
+			++d->p;
+
+			if (VEC_PUSH_STR(&d->vec, "signed ") == false)
+				return (false);
+
+			break;
+		case 'P' :
+			++d->p;
+
+			if (*d->p == 'F')
+				return (read_func_ptr(d));
+			else
+				d->ptr = true;
+
+			break;
+		case 'R' :
+			++d->p;
+
+			d->ref = true;
+
+			break;
+		case 'F' :
+			break;
+		case 'A' :
+			++d->p;
+
+			if (read_array(d) == false)
+				return (false);
+
+			break;
+		case 'M' :
+			++d->p;
+
+			if (read_memptr(d) == false)
+				return (false);
+
+			break;
+		default :
+			break;
+		}
+	}
+
+	if (ELFTC_ISDIGIT(*d->p))
+		return (read_class(d));
+
+	switch (*d->p) {
+	case 'Q' :
+		++d->p;
+
+		return (read_qual_name(d));
+	case 'v' :
+		++d->p;
+
+		return (VEC_PUSH_STR(&d->vec, "void"));
+	case 'b':
+		++d->p;
+
+		return(VEC_PUSH_STR(&d->vec, "bool"));
+	case 'c' :
+		++d->p;
+
+		return (VEC_PUSH_STR(&d->vec, "char"));
+	case 's' :
+		++d->p;
+
+		return (VEC_PUSH_STR(&d->vec, "short"));
+	case 'i' :
+		++d->p;
+
+		return (VEC_PUSH_STR(&d->vec, "int"));
+	case 'l' :
+		++d->p;
+
+		return (VEC_PUSH_STR(&d->vec, "long"));
+	case 'f' :
+		++d->p;
+
+		return (VEC_PUSH_STR(&d->vec, "float"));
+	case 'd':
+		++d->p;
+
+		return (VEC_PUSH_STR(&d->vec, "double"));
+	case 'r':
+		++d->p;
+
+		return (VEC_PUSH_STR(&d->vec, "long double"));
+	case 'e':
+		++d->p;
+
+		return (VEC_PUSH_STR(&d->vec, "..."));
+	case 'w':
+		++d->p;
+
+		return (VEC_PUSH_STR(&d->vec, "wchar_t"));
+	case 'x':
+		++d->p;
+
+		return (VEC_PUSH_STR(&d->vec, "long long"));
+	default:
+		return (false);
+	};
+
+	/* NOTREACHED */
+	return (false);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,3991 @@
+/*-
+ * Copyright (c) 2007 Hyogeol Lee <hyogeollee@gmail.com>
+ * Copyright (c) 2015-2017 Kai Wang <kaiwang27@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/types.h>
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <libelftc.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "_libelftc.h"
+
+ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3583 2017-10-15 15:38:47Z emaste $");
+
+/**
+ * @file cpp_demangle.c
+ * @brief Decode IA-64 C++ ABI style implementation.
+ *
+ * IA-64 standard ABI(Itanium C++ ABI) references.
+ *
+ * http://www.codesourcery.com/cxx-abi/abi.html#mangling \n
+ * http://www.codesourcery.com/cxx-abi/abi-mangling.html
+ */
+
+enum type_qualifier {
+	TYPE_PTR, TYPE_REF, TYPE_CMX, TYPE_IMG, TYPE_EXT, TYPE_RST, TYPE_VAT,
+	TYPE_CST, TYPE_VEC, TYPE_RREF
+};
+
+struct vector_type_qualifier {
+	size_t size, capacity;
+	enum type_qualifier *q_container;
+	struct vector_str ext_name;
+};
+
+enum read_cmd {
+	READ_FAIL, READ_NEST, READ_TMPL, READ_EXPR, READ_EXPL, READ_LOCAL,
+	READ_TYPE, READ_FUNC, READ_PTRMEM
+};
+
+struct read_cmd_item {
+	enum read_cmd cmd;
+	void *data;
+};
+
+struct vector_read_cmd {
+	size_t size, capacity;
+	struct read_cmd_item *r_container;
+};
+
+enum push_qualifier {
+	PUSH_ALL_QUALIFIER,
+	PUSH_CV_QUALIFIER,
+	PUSH_NON_CV_QUALIFIER,
+};
+
+struct cpp_demangle_data {
+	struct vector_str	 output;	/* output string vector */
+	struct vector_str	 subst;		/* substitution string vector */
+	struct vector_str	 tmpl;
+	struct vector_str	 class_type;
+	struct vector_str	*cur_output;	/* ptr to current output vec */
+	struct vector_read_cmd	 cmd;
+	bool			 mem_rst;	/* restrict member function */
+	bool			 mem_vat;	/* volatile member function */
+	bool			 mem_cst;	/* const member function */
+	bool			 mem_ref;	/* lvalue-ref member func */
+	bool			 mem_rref;	/* rvalue-ref member func */
+	bool			 is_tmpl;	/* template args */
+	bool			 is_functype;	/* function type */
+	bool			 ref_qualifier; /* ref qualifier */
+	enum type_qualifier	 ref_qualifier_type; /* ref qualifier type */
+	enum push_qualifier	 push_qualifier; /* which qualifiers to push */
+	int			 func_type;
+	const char		*cur;		/* current mangled name ptr */
+	const char		*last_sname;	/* last source name */
+};
+
+struct type_delimit {
+	bool paren;
+	bool firstp;
+};
+
+#define	CPP_DEMANGLE_TRY_LIMIT	128
+#define	FLOAT_SPRINTF_TRY_LIMIT	5
+#define	FLOAT_QUADRUPLE_BYTES	16
+#define	FLOAT_EXTENED_BYTES	10
+
+#define SIMPLE_HASH(x,y)	(64 * x + y)
+#define DEM_PUSH_STR(d,s)	cpp_demangle_push_str((d), (s), strlen((s)))
+#define VEC_PUSH_STR(d,s)	vector_str_push((d), (s), strlen((s)))
+
+static void	cpp_demangle_data_dest(struct cpp_demangle_data *);
+static int	cpp_demangle_data_init(struct cpp_demangle_data *,
+		    const char *);
+static int	cpp_demangle_get_subst(struct cpp_demangle_data *, size_t);
+static int	cpp_demangle_get_tmpl_param(struct cpp_demangle_data *, size_t);
+static int	cpp_demangle_push_fp(struct cpp_demangle_data *,
+		    char *(*)(const char *, size_t));
+static int	cpp_demangle_push_str(struct cpp_demangle_data *, const char *,
+		    size_t);
+static int	cpp_demangle_pop_str(struct cpp_demangle_data *);
+static int	cpp_demangle_push_subst(struct cpp_demangle_data *,
+		    const char *, size_t);
+static int	cpp_demangle_push_subst_v(struct cpp_demangle_data *,
+		    struct vector_str *);
+static int	cpp_demangle_push_type_qualifier(struct cpp_demangle_data *,
+		    struct vector_type_qualifier *, const char *);
+static int	cpp_demangle_read_array(struct cpp_demangle_data *);
+static int	cpp_demangle_read_encoding(struct cpp_demangle_data *);
+static int	cpp_demangle_read_expr_primary(struct cpp_demangle_data *);
+static int	cpp_demangle_read_expression(struct cpp_demangle_data *);
+static int	cpp_demangle_read_expression_flat(struct cpp_demangle_data *,
+		    char **);
+static int	cpp_demangle_read_expression_binary(struct cpp_demangle_data *,
+		    const char *, size_t);
+static int	cpp_demangle_read_expression_unary(struct cpp_demangle_data *,
+		    const char *, size_t);
+static int	cpp_demangle_read_expression_trinary(struct cpp_demangle_data *,
+		    const char *, size_t, const char *, size_t);
+static int	cpp_demangle_read_function(struct cpp_demangle_data *, int *,
+		    struct vector_type_qualifier *);
+static int	cpp_demangle_local_source_name(struct cpp_demangle_data *ddata);
+static int	cpp_demangle_read_local_name(struct cpp_demangle_data *);
+static int	cpp_demangle_read_name(struct cpp_demangle_data *);
+static int	cpp_demangle_read_name_flat(struct cpp_demangle_data *,
+		    char**);
+static int	cpp_demangle_read_nested_name(struct cpp_demangle_data *);
+static int	cpp_demangle_read_number(struct cpp_demangle_data *, long *);
+static int	cpp_demangle_read_number_as_string(struct cpp_demangle_data *,
+		    char **);
+static int	cpp_demangle_read_nv_offset(struct cpp_demangle_data *);
+static int	cpp_demangle_read_offset(struct cpp_demangle_data *);
+static int	cpp_demangle_read_offset_number(struct cpp_demangle_data *);
+static int	cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *,
+		    struct vector_type_qualifier *);
+static int	cpp_demangle_read_sname(struct cpp_demangle_data *);
+static int	cpp_demangle_read_subst(struct cpp_demangle_data *);
+static int	cpp_demangle_read_subst_std(struct cpp_demangle_data *);
+static int	cpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data *,
+		    const char *);
+static int	cpp_demangle_read_tmpl_arg(struct cpp_demangle_data *);
+static int	cpp_demangle_read_tmpl_args(struct cpp_demangle_data *);
+static int	cpp_demangle_read_tmpl_param(struct cpp_demangle_data *);
+static int	cpp_demangle_read_type(struct cpp_demangle_data *,
+		    struct type_delimit *);
+static int	cpp_demangle_read_type_flat(struct cpp_demangle_data *,
+		    char **);
+static int	cpp_demangle_read_uqname(struct cpp_demangle_data *);
+static int	cpp_demangle_read_v_offset(struct cpp_demangle_data *);
+static char	*decode_fp_to_double(const char *, size_t);
+static char	*decode_fp_to_float(const char *, size_t);
+static char	*decode_fp_to_float128(const char *, size_t);
+static char	*decode_fp_to_float80(const char *, size_t);
+static char	*decode_fp_to_long_double(const char *, size_t);
+static int	hex_to_dec(char);
+static void	vector_read_cmd_dest(struct vector_read_cmd *);
+static struct read_cmd_item *vector_read_cmd_find(struct vector_read_cmd *,
+		    enum read_cmd);
+static int	vector_read_cmd_init(struct vector_read_cmd *);
+static int	vector_read_cmd_pop(struct vector_read_cmd *);
+static int	vector_read_cmd_push(struct vector_read_cmd *, enum read_cmd,
+		    void *);
+static void	vector_type_qualifier_dest(struct vector_type_qualifier *);
+static int	vector_type_qualifier_init(struct vector_type_qualifier *);
+static int	vector_type_qualifier_push(struct vector_type_qualifier *,
+		    enum type_qualifier);
+
+/**
+ * @brief Decode the input string by IA-64 C++ ABI style.
+ *
+ * GNU GCC v3 use IA-64 standard ABI.
+ * @return New allocated demangled string or NULL if failed.
+ * @todo 1. Testing and more test case. 2. Code cleaning.
+ */
+char *
+cpp_demangle_gnu3(const char *org)
+{
+	struct cpp_demangle_data ddata;
+	struct vector_str ret_type;
+	struct type_delimit td;
+	ssize_t org_len;
+	unsigned int limit;
+	char *rtn;
+	bool has_ret, more_type;
+
+	if (org == NULL || (org_len = strlen(org)) < 2)
+		return (NULL);
+
+	if (org_len > 11 && !strncmp(org, "_GLOBAL__I_", 11)) {
+		if ((rtn = malloc(org_len + 19)) == NULL)
+			return (NULL);
+		snprintf(rtn, org_len + 19,
+		    "global constructors keyed to %s", org + 11);
+		return (rtn);
+	}
+
+	if (org[0] != '_' || org[1] != 'Z')
+		return (NULL);
+
+	if (!cpp_demangle_data_init(&ddata, org + 2))
+		return (NULL);
+
+	rtn = NULL;
+	has_ret = more_type = false;
+
+	if (!cpp_demangle_read_encoding(&ddata))
+		goto clean;
+
+	/*
+	 * Pop function name from substitution candidate list.
+	 */
+	if (*ddata.cur != 0 && ddata.subst.size >= 1) {
+		if (!vector_str_pop(&ddata.subst))
+			goto clean;
+	}
+
+	td.paren = false;
+	td.firstp = true;
+	limit = 0;
+
+	/*
+	 * The first type is a return type if we just demangled template
+	 * args. (the template args is right next to the function name,
+	 * which means it's a template function)
+	 */
+	if (ddata.is_tmpl) {
+		ddata.is_tmpl = false;
+		if (!vector_str_init(&ret_type))
+			goto clean;
+		ddata.cur_output = &ret_type;
+		has_ret = true;
+	}
+
+	while (*ddata.cur != '\0') {
+		/*
+		 * Breaking at some gcc info at tail. e.g) @@GLIBCXX_3.4
+		 */
+		if (*ddata.cur == '@' && *(ddata.cur + 1) == '@')
+			break;
+
+		if (has_ret) {
+			/* Read return type */
+			if (!cpp_demangle_read_type(&ddata, NULL))
+				goto clean;
+		} else {
+			/* Read function arg type */
+			if (!cpp_demangle_read_type(&ddata, &td))
+				goto clean;
+		}
+
+		if (has_ret) {
+			/* Push return type to the beginning */
+			if (!VEC_PUSH_STR(&ret_type, " "))
+				goto clean;
+			if (!vector_str_push_vector_head(&ddata.output,
+			    &ret_type))
+				goto clean;
+			ddata.cur_output = &ddata.output;
+			vector_str_dest(&ret_type);
+			has_ret = false;
+			more_type = true;
+		} else if (more_type)
+			more_type = false;
+		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
+			goto clean;
+	}
+	if (more_type)
+		goto clean;
+
+	if (ddata.output.size == 0)
+		goto clean;
+	if (td.paren && !VEC_PUSH_STR(&ddata.output, ")"))
+		goto clean;
+	if (ddata.mem_vat && !VEC_PUSH_STR(&ddata.output, " volatile"))
+		goto clean;
+	if (ddata.mem_cst && !VEC_PUSH_STR(&ddata.output, " const"))
+		goto clean;
+	if (ddata.mem_rst && !VEC_PUSH_STR(&ddata.output, " restrict"))
+		goto clean;
+	if (ddata.mem_ref && !VEC_PUSH_STR(&ddata.output, " &"))
+		goto clean;
+	if (ddata.mem_rref && !VEC_PUSH_STR(&ddata.output, " &&"))
+		goto clean;
+
+	rtn = vector_str_get_flat(&ddata.output, (size_t *) NULL);
+
+clean:
+	if (has_ret)
+		vector_str_dest(&ret_type);
+
+	cpp_demangle_data_dest(&ddata);
+
+	return (rtn);
+}
+
+static void
+cpp_demangle_data_dest(struct cpp_demangle_data *d)
+{
+
+	if (d == NULL)
+		return;
+
+	vector_read_cmd_dest(&d->cmd);
+	vector_str_dest(&d->class_type);
+	vector_str_dest(&d->tmpl);
+	vector_str_dest(&d->subst);
+	vector_str_dest(&d->output);
+}
+
+static int
+cpp_demangle_data_init(struct cpp_demangle_data *d, const char *cur)
+{
+
+	if (d == NULL || cur == NULL)
+		return (0);
+
+	if (!vector_str_init(&d->output))
+		return (0);
+	if (!vector_str_init(&d->subst))
+		goto clean1;
+	if (!vector_str_init(&d->tmpl))
+		goto clean2;
+	if (!vector_str_init(&d->class_type))
+		goto clean3;
+	if (!vector_read_cmd_init(&d->cmd))
+		goto clean4;
+
+	assert(d->output.container != NULL);
+	assert(d->subst.container != NULL);
+	assert(d->tmpl.container != NULL);
+	assert(d->class_type.container != NULL);
+
+	d->mem_rst = false;
+	d->mem_vat = false;
+	d->mem_cst = false;
+	d->mem_ref = false;
+	d->mem_rref = false;
+	d->is_tmpl = false;
+	d->is_functype = false;
+	d->ref_qualifier = false;
+	d->push_qualifier = PUSH_ALL_QUALIFIER;
+	d->func_type = 0;
+	d->cur = cur;
+	d->cur_output = &d->output;
+	d->last_sname = NULL;
+
+	return (1);
+
+clean4:
+	vector_str_dest(&d->class_type);
+clean3:
+	vector_str_dest(&d->tmpl);
+clean2:
+	vector_str_dest(&d->subst);
+clean1:
+	vector_str_dest(&d->output);
+
+	return (0);
+}
+
+static int
+cpp_demangle_push_fp(struct cpp_demangle_data *ddata,
+    char *(*decoder)(const char *, size_t))
+{
+	size_t len;
+	int rtn;
+	const char *fp;
+	char *f;
+
+	if (ddata == NULL || decoder == NULL)
+		return (0);
+
+	fp = ddata->cur;
+	while (*ddata->cur != 'E')
+		++ddata->cur;
+
+	if ((f = decoder(fp, ddata->cur - fp)) == NULL)
+		return (0);
+
+	rtn = 0;
+	if ((len = strlen(f)) > 0)
+		rtn = cpp_demangle_push_str(ddata, f, len);
+
+	free(f);
+
+	++ddata->cur;
+
+	return (rtn);
+}
+
+static int
+cpp_demangle_push_str(struct cpp_demangle_data *ddata, const char *str,
+    size_t len)
+{
+
+	if (ddata == NULL || str == NULL || len == 0)
+		return (0);
+
+	/*
+	 * is_tmpl is used to check if the type (function arg) is right next
+	 * to template args, and should always be cleared whenever new string
+	 * pushed.
+	 */
+	ddata->is_tmpl = false;
+
+	return (vector_str_push(ddata->cur_output, str, len));
+}
+
+static int
+cpp_demangle_pop_str(struct cpp_demangle_data *ddata)
+{
+
+	if (ddata == NULL)
+		return (0);
+
+	return (vector_str_pop(ddata->cur_output));
+}
+
+static int
+cpp_demangle_push_subst(struct cpp_demangle_data *ddata, const char *str,
+    size_t len)
+{
+
+	if (ddata == NULL || str == NULL || len == 0)
+		return (0);
+
+	if (!vector_str_find(&ddata->subst, str, len))
+		return (vector_str_push(&ddata->subst, str, len));
+
+	return (1);
+}
+
+static int
+cpp_demangle_push_subst_v(struct cpp_demangle_data *ddata, struct vector_str *v)
+{
+	size_t str_len;
+	int rtn;
+	char *str;
+
+	if (ddata == NULL || v == NULL)
+		return (0);
+
+	if ((str = vector_str_get_flat(v, &str_len)) == NULL)
+		return (0);
+
+	rtn = cpp_demangle_push_subst(ddata, str, str_len);
+
+	free(str);
+
+	return (rtn);
+}
+
+static int
+cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
+    struct vector_type_qualifier *v, const char *type_str)
+{
+	struct vector_str subst_v;
+	enum type_qualifier t;
+	size_t idx, e_idx, e_len;
+	char *buf;
+	int rtn;
+	bool cv;
+
+	if (ddata == NULL || v == NULL)
+		return (0);
+
+	if ((idx = v->size) == 0)
+		return (1);
+
+	rtn = 0;
+	if (type_str != NULL) {
+		if (!vector_str_init(&subst_v))
+			return (0);
+		if (!VEC_PUSH_STR(&subst_v, type_str))
+			goto clean;
+	}
+
+	cv = true;
+	e_idx = 0;
+	while (idx > 0) {
+		switch (v->q_container[idx - 1]) {
+		case TYPE_PTR:
+			cv = false;
+			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
+				break;
+			if (!DEM_PUSH_STR(ddata, "*"))
+				goto clean;
+			if (type_str != NULL) {
+				if (!VEC_PUSH_STR(&subst_v, "*"))
+					goto clean;
+				if (!cpp_demangle_push_subst_v(ddata,
+				    &subst_v))
+					goto clean;
+			}
+			break;
+
+		case TYPE_REF:
+			cv = false;
+			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
+				break;
+			if (!DEM_PUSH_STR(ddata, "&"))
+				goto clean;
+			if (type_str != NULL) {
+				if (!VEC_PUSH_STR(&subst_v, "&"))
+					goto clean;
+				if (!cpp_demangle_push_subst_v(ddata,
+				    &subst_v))
+					goto clean;
+			}
+			break;
+
+		case TYPE_RREF:
+			cv = false;
+			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
+				break;
+			if (!DEM_PUSH_STR(ddata, "&&"))
+				goto clean;
+			if (type_str != NULL) {
+				if (!VEC_PUSH_STR(&subst_v, "&&"))
+					goto clean;
+				if (!cpp_demangle_push_subst_v(ddata,
+				    &subst_v))
+					goto clean;
+			}
+			break;
+
+		case TYPE_CMX:
+			cv = false;
+			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
+				break;
+			if (!DEM_PUSH_STR(ddata, " complex"))
+				goto clean;
+			if (type_str != NULL) {
+				if (!VEC_PUSH_STR(&subst_v, " complex"))
+					goto clean;
+				if (!cpp_demangle_push_subst_v(ddata,
+				    &subst_v))
+					goto clean;
+			}
+			break;
+
+		case TYPE_IMG:
+			cv = false;
+			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
+				break;
+			if (!DEM_PUSH_STR(ddata, " imaginary"))
+				goto clean;
+			if (type_str != NULL) {
+				if (!VEC_PUSH_STR(&subst_v, " imaginary"))
+					goto clean;
+				if (!cpp_demangle_push_subst_v(ddata,
+				    &subst_v))
+					goto clean;
+			}
+			break;
+
+		case TYPE_EXT:
+			cv = false;
+			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
+				break;
+			if (v->ext_name.size == 0 ||
+			    e_idx > v->ext_name.size - 1)
+				goto clean;
+			if ((e_len = strlen(v->ext_name.container[e_idx])) ==
+			    0)
+				goto clean;
+			if ((buf = malloc(e_len + 2)) == NULL)
+				goto clean;
+			snprintf(buf, e_len + 2, " %s",
+			    v->ext_name.container[e_idx]);
+
+			if (!DEM_PUSH_STR(ddata, buf)) {
+				free(buf);
+				goto clean;
+			}
+
+			if (type_str != NULL) {
+				if (!VEC_PUSH_STR(&subst_v, buf)) {
+					free(buf);
+					goto clean;
+				}
+				if (!cpp_demangle_push_subst_v(ddata,
+				    &subst_v)) {
+					free(buf);
+					goto clean;
+				}
+			}
+			free(buf);
+			++e_idx;
+			break;
+
+		case TYPE_RST:
+			if (ddata->push_qualifier == PUSH_NON_CV_QUALIFIER &&
+			    cv)
+				break;
+			if (ddata->push_qualifier == PUSH_CV_QUALIFIER && !cv)
+				break;
+			if (!DEM_PUSH_STR(ddata, " restrict"))
+				goto clean;
+			if (type_str != NULL) {
+				if (!VEC_PUSH_STR(&subst_v, " restrict"))
+					goto clean;
+				if (idx - 1 > 0) {
+					t = v->q_container[idx - 2];
+					if (t == TYPE_RST || t == TYPE_VAT ||
+					    t == TYPE_CST)
+						break;
+				}
+				if (!cpp_demangle_push_subst_v(ddata,
+				    &subst_v))
+					goto clean;
+			}
+			break;
+
+		case TYPE_VAT:
+			if (ddata->push_qualifier == PUSH_NON_CV_QUALIFIER &&
+			    cv)
+				break;
+			if (ddata->push_qualifier == PUSH_CV_QUALIFIER && !cv)
+				break;
+			if (!DEM_PUSH_STR(ddata, " volatile"))
+				goto clean;
+			if (type_str != NULL) {
+				if (!VEC_PUSH_STR(&subst_v, " volatile"))
+					goto clean;
+				if (idx - 1 > 0) {
+					t = v->q_container[idx - 2];
+					if (t == TYPE_RST || t == TYPE_VAT ||
+					    t == TYPE_CST)
+						break;
+				}
+				if (!cpp_demangle_push_subst_v(ddata,
+				    &subst_v))
+					goto clean;
+			}
+			break;
+
+		case TYPE_CST:
+			if (ddata->push_qualifier == PUSH_NON_CV_QUALIFIER &&
+			    cv)
+				break;
+			if (ddata->push_qualifier == PUSH_CV_QUALIFIER && !cv)
+				break;
+			if (!DEM_PUSH_STR(ddata, " const"))
+				goto clean;
+			if (type_str != NULL) {
+				if (!VEC_PUSH_STR(&subst_v, " const"))
+					goto clean;
+				if (idx - 1 > 0) {
+					t = v->q_container[idx - 2];
+					if (t == TYPE_RST || t == TYPE_VAT ||
+					    t == TYPE_CST)
+						break;
+				}
+				if (!cpp_demangle_push_subst_v(ddata,
+				    &subst_v))
+					goto clean;
+			}
+			break;
+
+		case TYPE_VEC:
+			cv = false;
+			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
+				break;
+			if (v->ext_name.size == 0 ||
+			    e_idx > v->ext_name.size - 1)
+				goto clean;
+			if ((e_len = strlen(v->ext_name.container[e_idx])) ==
+			    0)
+				goto clean;
+			if ((buf = malloc(e_len + 12)) == NULL)
+				goto clean;
+			snprintf(buf, e_len + 12, " __vector(%s)",
+			    v->ext_name.container[e_idx]);
+			if (!DEM_PUSH_STR(ddata, buf)) {
+				free(buf);
+				goto clean;
+			}
+			if (type_str != NULL) {
+				if (!VEC_PUSH_STR(&subst_v, buf)) {
+					free(buf);
+					goto clean;
+				}
+				if (!cpp_demangle_push_subst_v(ddata,
+				    &subst_v)) {
+					free(buf);
+					goto clean;
+				}
+			}
+			free(buf);
+			++e_idx;
+			break;
+		}
+		--idx;
+	}
+
+	rtn = 1;
+clean:
+	if (type_str != NULL)
+		vector_str_dest(&subst_v);
+
+	return (rtn);
+}
+
+static int
+cpp_demangle_get_subst(struct cpp_demangle_data *ddata, size_t idx)
+{
+	size_t len;
+
+	if (ddata == NULL || ddata->subst.size <= idx)
+		return (0);
+	if ((len = strlen(ddata->subst.container[idx])) == 0)
+		return (0);
+	if (!cpp_demangle_push_str(ddata, ddata->subst.container[idx], len))
+		return (0);
+
+	/* skip '_' */
+	++ddata->cur;
+
+	return (1);
+}
+
+static int
+cpp_demangle_get_tmpl_param(struct cpp_demangle_data *ddata, size_t idx)
+{
+	size_t len;
+
+	if (ddata == NULL || ddata->tmpl.size <= idx)
+		return (0);
+	if ((len = strlen(ddata->tmpl.container[idx])) == 0)
+		return (0);
+	if (!cpp_demangle_push_str(ddata, ddata->tmpl.container[idx], len))
+		return (0);
+
+	++ddata->cur;
+
+	return (1);
+}
+
+static int
+cpp_demangle_read_array(struct cpp_demangle_data *ddata)
+{
+	size_t i, num_len, exp_len, p_idx, idx;
+	const char *num;
+	char *exp;
+
+	if (ddata == NULL || *(++ddata->cur) == '\0')
+		return (0);
+
+	if (*ddata->cur == '_') {
+		if (*(++ddata->cur) == '\0')
+			return (0);
+
+		if (!cpp_demangle_read_type(ddata, NULL))
+			return (0);
+
+		if (!DEM_PUSH_STR(ddata, "[]"))
+			return (0);
+	} else {
+		if (ELFTC_ISDIGIT(*ddata->cur) != 0) {
+			num = ddata->cur;
+			while (ELFTC_ISDIGIT(*ddata->cur) != 0)
+				++ddata->cur;
+			if (*ddata->cur != '_')
+				return (0);
+			num_len = ddata->cur - num;
+			assert(num_len > 0);
+			if (*(++ddata->cur) == '\0')
+				return (0);
+			if (!cpp_demangle_read_type(ddata, NULL))
+				return (0);
+			if (!DEM_PUSH_STR(ddata, "["))
+				return (0);
+			if (!cpp_demangle_push_str(ddata, num, num_len))
+				return (0);
+			if (!DEM_PUSH_STR(ddata, "]"))
+				return (0);
+		} else {
+			p_idx = ddata->output.size;
+			if (!cpp_demangle_read_expression(ddata))
+				return (0);
+			if ((exp = vector_str_substr(&ddata->output, p_idx,
+				 ddata->output.size - 1, &exp_len)) == NULL)
+				return (0);
+			idx = ddata->output.size;
+			for (i = p_idx; i < idx; ++i)
+				if (!vector_str_pop(&ddata->output)) {
+					free(exp);
+					return (0);
+				}
+			if (*ddata->cur != '_') {
+				free(exp);
+				return (0);
+			}
+			++ddata->cur;
+			if (*ddata->cur == '\0') {
+				free(exp);
+				return (0);
+			}
+			if (!cpp_demangle_read_type(ddata, NULL)) {
+				free(exp);
+				return (0);
+			}
+			if (!DEM_PUSH_STR(ddata, "[")) {
+				free(exp);
+				return (0);
+			}
+			if (!cpp_demangle_push_str(ddata, exp, exp_len)) {
+				free(exp);
+				return (0);
+			}
+			if (!DEM_PUSH_STR(ddata, "]")) {
+				free(exp);
+				return (0);
+			}
+			free(exp);
+		}
+	}
+
+	return (1);
+}
+
+static int
+cpp_demangle_read_expr_primary(struct cpp_demangle_data *ddata)
+{
+	const char *num;
+
+	if (ddata == NULL || *(++ddata->cur) == '\0')
+		return (0);
+
+	if (*ddata->cur == '_' && *(ddata->cur + 1) == 'Z') {
+		ddata->cur += 2;
+		if (*ddata->cur == '\0')
+			return (0);
+		if (!cpp_demangle_read_encoding(ddata))
+			return (0);
+		++ddata->cur;
+		return (1);
+	}
+
+	switch (*ddata->cur) {
+	case 'b':
+		if (*(ddata->cur + 2) != 'E')
+			return (0);
+		switch (*(++ddata->cur)) {
+		case '0':
+			ddata->cur += 2;
+			return (DEM_PUSH_STR(ddata, "false"));
+		case '1':
+			ddata->cur += 2;
+			return (DEM_PUSH_STR(ddata, "true"));
+		default:
+			return (0);
+		}
+
+	case 'd':
+		++ddata->cur;
+		return (cpp_demangle_push_fp(ddata, decode_fp_to_double));
+
+	case 'e':
+		++ddata->cur;
+		if (sizeof(long double) == 10)
+			return (cpp_demangle_push_fp(ddata,
+			    decode_fp_to_double));
+		return (cpp_demangle_push_fp(ddata, decode_fp_to_float80));
+
+	case 'f':
+		++ddata->cur;
+		return (cpp_demangle_push_fp(ddata, decode_fp_to_float));
+
+	case 'g':
+		++ddata->cur;
+		if (sizeof(long double) == 16)
+			return (cpp_demangle_push_fp(ddata,
+			    decode_fp_to_double));
+		return (cpp_demangle_push_fp(ddata, decode_fp_to_float128));
+
+	case 'i':
+	case 'j':
+	case 'l':
+	case 'm':
+	case 'n':
+	case 's':
+	case 't':
+	case 'x':
+	case 'y':
+		if (*(++ddata->cur) == 'n') {
+			if (!DEM_PUSH_STR(ddata, "-"))
+				return (0);
+			++ddata->cur;
+		}
+		num = ddata->cur;
+		while (*ddata->cur != 'E') {
+			if (!ELFTC_ISDIGIT(*ddata->cur))
+				return (0);
+			++ddata->cur;
+		}
+		++ddata->cur;
+		return (cpp_demangle_push_str(ddata, num,
+		    ddata->cur - num - 1));
+
+	default:
+		return (0);
+	}
+}
+
+static int
+cpp_demangle_read_expression(struct cpp_demangle_data *ddata)
+{
+
+	if (ddata == NULL || *ddata->cur == '\0')
+		return (0);
+
+	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
+	case SIMPLE_HASH('s', 't'):
+		ddata->cur += 2;
+		return (cpp_demangle_read_type(ddata, NULL));
+
+	case SIMPLE_HASH('s', 'r'):
+		ddata->cur += 2;
+		if (!cpp_demangle_read_type(ddata, NULL))
+			return (0);
+		if (!cpp_demangle_read_uqname(ddata))
+			return (0);
+		if (*ddata->cur == 'I')
+			return (cpp_demangle_read_tmpl_args(ddata));
+		return (1);
+
+	case SIMPLE_HASH('a', 'a'):
+		/* operator && */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "&&", 2));
+
+	case SIMPLE_HASH('a', 'd'):
+		/* operator & (unary) */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_unary(ddata, "&", 1));
+
+	case SIMPLE_HASH('a', 'n'):
+		/* operator & */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "&", 1));
+
+	case SIMPLE_HASH('a', 'N'):
+		/* operator &= */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "&=", 2));
+
+	case SIMPLE_HASH('a', 'S'):
+		/* operator = */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "=", 1));
+
+	case SIMPLE_HASH('c', 'l'):
+		/* operator () */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "()", 2));
+
+	case SIMPLE_HASH('c', 'm'):
+		/* operator , */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, ",", 1));
+
+	case SIMPLE_HASH('c', 'o'):
+		/* operator ~ */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "~", 1));
+
+	case SIMPLE_HASH('c', 'v'):
+		/* operator (cast) */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "(cast)", 6));
+
+	case SIMPLE_HASH('d', 'a'):
+		/* operator delete [] */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_unary(ddata, "delete []", 9));
+
+	case SIMPLE_HASH('d', 'e'):
+		/* operator * (unary) */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_unary(ddata, "*", 1));
+
+	case SIMPLE_HASH('d', 'l'):
+		/* operator delete */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_unary(ddata, "delete", 6));
+
+	case SIMPLE_HASH('d', 'v'):
+		/* operator / */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "/", 1));
+
+	case SIMPLE_HASH('d', 'V'):
+		/* operator /= */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "/=", 2));
+
+	case SIMPLE_HASH('e', 'o'):
+		/* operator ^ */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "^", 1));
+
+	case SIMPLE_HASH('e', 'O'):
+		/* operator ^= */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "^=", 2));
+
+	case SIMPLE_HASH('e', 'q'):
+		/* operator == */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "==", 2));
+
+	case SIMPLE_HASH('g', 'e'):
+		/* operator >= */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, ">=", 2));
+
+	case SIMPLE_HASH('g', 't'):
+		/* operator > */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, ">", 1));
+
+	case SIMPLE_HASH('i', 'x'):
+		/* operator [] */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "[]", 2));
+
+	case SIMPLE_HASH('l', 'e'):
+		/* operator <= */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "<=", 2));
+
+	case SIMPLE_HASH('l', 's'):
+		/* operator << */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "<<", 2));
+
+	case SIMPLE_HASH('l', 'S'):
+		/* operator <<= */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "<<=", 3));
+
+	case SIMPLE_HASH('l', 't'):
+		/* operator < */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "<", 1));
+
+	case SIMPLE_HASH('m', 'i'):
+		/* operator - */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "-", 1));
+
+	case SIMPLE_HASH('m', 'I'):
+		/* operator -= */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "-=", 2));
+
+	case SIMPLE_HASH('m', 'l'):
+		/* operator * */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "*", 1));
+
+	case SIMPLE_HASH('m', 'L'):
+		/* operator *= */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "*=", 2));
+
+	case SIMPLE_HASH('m', 'm'):
+		/* operator -- */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "--", 2));
+
+	case SIMPLE_HASH('n', 'a'):
+		/* operator new[] */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_unary(ddata, "new []", 6));
+
+	case SIMPLE_HASH('n', 'e'):
+		/* operator != */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "!=", 2));
+
+	case SIMPLE_HASH('n', 'g'):
+		/* operator - (unary) */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_unary(ddata, "-", 1));
+
+	case SIMPLE_HASH('n', 't'):
+		/* operator ! */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "!", 1));
+
+	case SIMPLE_HASH('n', 'w'):
+		/* operator new */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_unary(ddata, "new", 3));
+
+	case SIMPLE_HASH('o', 'o'):
+		/* operator || */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "||", 2));
+
+	case SIMPLE_HASH('o', 'r'):
+		/* operator | */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "|", 1));
+
+	case SIMPLE_HASH('o', 'R'):
+		/* operator |= */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "|=", 2));
+
+	case SIMPLE_HASH('p', 'l'):
+		/* operator + */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "+", 1));
+
+	case SIMPLE_HASH('p', 'L'):
+		/* operator += */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "+=", 2));
+
+	case SIMPLE_HASH('p', 'm'):
+		/* operator ->* */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "->*", 3));
+
+	case SIMPLE_HASH('p', 'p'):
+		/* operator ++ */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "++", 2));
+
+	case SIMPLE_HASH('p', 's'):
+		/* operator + (unary) */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_unary(ddata, "+", 1));
+
+	case SIMPLE_HASH('p', 't'):
+		/* operator -> */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "->", 2));
+
+	case SIMPLE_HASH('q', 'u'):
+		/* operator ? */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_trinary(ddata, "?", 1,
+		    ":", 1));
+
+	case SIMPLE_HASH('r', 'm'):
+		/* operator % */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "%", 1));
+
+	case SIMPLE_HASH('r', 'M'):
+		/* operator %= */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, "%=", 2));
+
+	case SIMPLE_HASH('r', 's'):
+		/* operator >> */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, ">>", 2));
+
+	case SIMPLE_HASH('r', 'S'):
+		/* operator >>= */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_binary(ddata, ">>=", 3));
+
+	case SIMPLE_HASH('r', 'z'):
+		/* operator sizeof */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_unary(ddata, "sizeof", 6));
+
+	case SIMPLE_HASH('s', 'v'):
+		/* operator sizeof */
+		ddata->cur += 2;
+		return (cpp_demangle_read_expression_unary(ddata, "sizeof", 6));
+	}
+
+	switch (*ddata->cur) {
+	case 'L':
+		return (cpp_demangle_read_expr_primary(ddata));
+	case 'T':
+		return (cpp_demangle_read_tmpl_param(ddata));
+	}
+
+	return (0);
+}
+
+static int
+cpp_demangle_read_expression_flat(struct cpp_demangle_data *ddata, char **str)
+{
+	struct vector_str *output;
+	size_t i, p_idx, idx, exp_len;
+	char *exp;
+
+	output = &ddata->output;
+
+	p_idx = output->size;
+
+	if (!cpp_demangle_read_expression(ddata))
+		return (0);
+
+	if ((exp = vector_str_substr(output, p_idx, output->size - 1,
+	    &exp_len)) == NULL)
+		return (0);
+
+	idx = output->size;
+	for (i = p_idx; i < idx; ++i) {
+		if (!vector_str_pop(output)) {
+			free(exp);
+			return (0);
+		}
+	}
+
+	*str = exp;
+
+	return (1);
+}
+
+static int
+cpp_demangle_read_expression_binary(struct cpp_demangle_data *ddata,
+    const char *name, size_t len)
+{
+
+	if (ddata == NULL || name == NULL || len == 0)
+		return (0);
+	if (!cpp_demangle_read_expression(ddata))
+		return (0);
+	if (!cpp_demangle_push_str(ddata, name, len))
+		return (0);
+
+	return (cpp_demangle_read_expression(ddata));
+}
+
+static int
+cpp_demangle_read_expression_unary(struct cpp_demangle_data *ddata,
+    const char *name, size_t len)
+{
+
+	if (ddata == NULL || name == NULL || len == 0)
+		return (0);
+	if (!cpp_demangle_read_expression(ddata))
+		return (0);
+
+	return (cpp_demangle_push_str(ddata, name, len));
+}
+
+static int
+cpp_demangle_read_expression_trinary(struct cpp_demangle_data *ddata,
+    const char *name1, size_t len1, const char *name2, size_t len2)
+{
+
+	if (ddata == NULL || name1 == NULL || len1 == 0 || name2 == NULL ||
+	    len2 == 0)
+		return (0);
+
+	if (!cpp_demangle_read_expression(ddata))
+		return (0);
+	if (!cpp_demangle_push_str(ddata, name1, len1))
+		return (0);
+	if (!cpp_demangle_read_expression(ddata))
+		return (0);
+	if (!cpp_demangle_push_str(ddata, name2, len2))
+		return (0);
+
+	return (cpp_demangle_read_expression(ddata));
+}
+
+static int
+cpp_demangle_read_function(struct cpp_demangle_data *ddata, int *ext_c,
+    struct vector_type_qualifier *v)
+{
+	struct type_delimit td;
+	struct read_cmd_item *rc;
+	size_t class_type_size, class_type_len, limit;
+	const char *class_type;
+	int i;
+	bool paren, non_cv_qualifier;
+
+	if (ddata == NULL || *ddata->cur != 'F' || v == NULL)
+		return (0);
+
+	++ddata->cur;
+	if (*ddata->cur == 'Y') {
+		if (ext_c != NULL)
+			*ext_c = 1;
+		++ddata->cur;
+	}
+
+	/* Return type */
+	if (!cpp_demangle_read_type(ddata, NULL))
+		return (0);
+
+	if (*ddata->cur != 'E') {
+		if (!DEM_PUSH_STR(ddata, " "))
+			return (0);
+
+		non_cv_qualifier = false;
+		if (v->size > 0) {
+			for (i = 0; (size_t) i < v->size; i++) {
+				if (v->q_container[i] != TYPE_RST &&
+				    v->q_container[i] != TYPE_VAT &&
+				    v->q_container[i] != TYPE_CST) {
+					non_cv_qualifier = true;
+					break;
+				}
+			}
+		}
+
+		paren = false;
+		rc = vector_read_cmd_find(&ddata->cmd, READ_PTRMEM);
+		if (non_cv_qualifier || rc != NULL) {
+			if (!DEM_PUSH_STR(ddata, "("))
+				return (0);
+			paren = true;
+		}
+
+		/* Push non-cv qualifiers. */
+		ddata->push_qualifier = PUSH_NON_CV_QUALIFIER;
+		if (!cpp_demangle_push_type_qualifier(ddata, v, NULL))
+			return (0);
+
+		if (rc) {
+			if (non_cv_qualifier && !DEM_PUSH_STR(ddata, " "))
+				return (0);
+			if ((class_type_size = ddata->class_type.size) == 0)
+				return (0);
+			class_type =
+			    ddata->class_type.container[class_type_size - 1];
+			if (class_type == NULL)
+				return (0);
+			if ((class_type_len = strlen(class_type)) == 0)
+				return (0);
+			if (!cpp_demangle_push_str(ddata, class_type,
+			    class_type_len))
+				return (0);
+			if (!DEM_PUSH_STR(ddata, "::*"))
+				return (0);
+			/* Push pointer-to-member qualifiers. */
+			ddata->push_qualifier = PUSH_ALL_QUALIFIER;
+			if (!cpp_demangle_push_type_qualifier(ddata, rc->data,
+			    NULL))
+				return (0);
+			++ddata->func_type;
+		}
+
+		if (paren) {
+			if (!DEM_PUSH_STR(ddata, ")"))
+				return (0);
+			paren = false;
+		}
+
+		td.paren = false;
+		td.firstp = true;
+		limit = 0;
+		ddata->is_functype = true;
+		for (;;) {
+			if (!cpp_demangle_read_type(ddata, &td))
+				return (0);
+			if (*ddata->cur == 'E')
+				break;
+			if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
+				return (0);
+		}
+		ddata->is_functype = false;
+		if (td.paren) {
+			if (!DEM_PUSH_STR(ddata, ")"))
+				return (0);
+			td.paren = false;
+		}
+
+		/* Push CV qualifiers. */
+		ddata->push_qualifier = PUSH_CV_QUALIFIER;
+		if (!cpp_demangle_push_type_qualifier(ddata, v, NULL))
+			return (0);
+
+		ddata->push_qualifier = PUSH_ALL_QUALIFIER;
+
+		/* Release type qualifier vector. */
+		vector_type_qualifier_dest(v);
+		if (!vector_type_qualifier_init(v))
+			return (0);
+
+		/* Push ref-qualifiers. */
+		if (ddata->ref_qualifier) {
+			switch (ddata->ref_qualifier_type) {
+			case TYPE_REF:
+				if (!DEM_PUSH_STR(ddata, " &"))
+					return (0);
+				break;
+			case TYPE_RREF:
+				if (!DEM_PUSH_STR(ddata, " &&"))
+					return (0);
+				break;
+			default:
+				return (0);
+			}
+			ddata->ref_qualifier = false;
+		}
+	}
+
+	++ddata->cur;
+
+	return (1);
+}
+
+/* read encoding, encoding are function name, data name, special-name */
+static int
+cpp_demangle_read_encoding(struct cpp_demangle_data *ddata)
+{
+	char *name, *type, *num_str;
+	long offset;
+	int rtn;
+
+	if (ddata == NULL || *ddata->cur == '\0')
+		return (0);
+
+	/* special name */
+	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
+	case SIMPLE_HASH('G', 'A'):
+		if (!DEM_PUSH_STR(ddata, "hidden alias for "))
+			return (0);
+		ddata->cur += 2;
+		if (*ddata->cur == '\0')
+			return (0);
+		return (cpp_demangle_read_encoding(ddata));
+
+	case SIMPLE_HASH('G', 'R'):
+		if (!DEM_PUSH_STR(ddata, "reference temporary #"))
+			return (0);
+		ddata->cur += 2;
+		if (*ddata->cur == '\0')
+			return (0);
+		if (!cpp_demangle_read_name_flat(ddata, &name))
+			return (0);
+		rtn = 0;
+		if (!cpp_demangle_read_number_as_string(ddata, &num_str))
+			goto clean1;
+		if (!DEM_PUSH_STR(ddata, num_str))
+			goto clean2;
+		if (!DEM_PUSH_STR(ddata, " for "))
+			goto clean2;
+		if (!DEM_PUSH_STR(ddata, name))
+			goto clean2;
+		rtn = 1;
+	clean2:
+		free(num_str);
+	clean1:
+		free(name);
+		return (rtn);
+
+	case SIMPLE_HASH('G', 'T'):
+		ddata->cur += 2;
+		if (*ddata->cur == '\0')
+			return (0);
+		switch (*ddata->cur) {
+		case 'n':
+			if (!DEM_PUSH_STR(ddata, "non-transaction clone for "))
+				return (0);
+			break;
+		case 't':
+		default:
+			if (!DEM_PUSH_STR(ddata, "transaction clone for "))
+				return (0);
+			break;
+		}
+		++ddata->cur;
+		return (cpp_demangle_read_encoding(ddata));
+
+	case SIMPLE_HASH('G', 'V'):
+		/* sentry object for 1 time init */
+		if (!DEM_PUSH_STR(ddata, "guard variable for "))
+			return (0);
+		ddata->cur += 2;
+		break;
+
+	case SIMPLE_HASH('T', 'c'):
+		/* virtual function covariant override thunk */
+		if (!DEM_PUSH_STR(ddata,
+		    "virtual function covariant override "))
+			return (0);
+		ddata->cur += 2;
+		if (*ddata->cur == '\0')
+			return (0);
+		if (!cpp_demangle_read_offset(ddata))
+			return (0);
+		if (!cpp_demangle_read_offset(ddata))
+			return (0);
+		return (cpp_demangle_read_encoding(ddata));
+
+	case SIMPLE_HASH('T', 'C'):
+		/* construction vtable */
+		if (!DEM_PUSH_STR(ddata, "construction vtable for "))
+			return (0);
+		ddata->cur += 2;
+		if (*ddata->cur == '\0')
+			return (0);
+		if (!cpp_demangle_read_type_flat(ddata, &type))
+			return (0);
+		rtn = 0;
+		if (!cpp_demangle_read_number(ddata, &offset))
+			goto clean3;
+		if (*ddata->cur++ != '_')
+			goto clean3;
+		if (!cpp_demangle_read_type(ddata, NULL))
+			goto clean3;
+		if (!DEM_PUSH_STR(ddata, "-in-"))
+			goto clean3;
+		if (!DEM_PUSH_STR(ddata, type))
+			goto clean3;
+		rtn = 1;
+	clean3:
+		free(type);
+		return (rtn);
+
+	case SIMPLE_HASH('T', 'D'):
+		/* typeinfo common proxy */
+		break;
+
+	case SIMPLE_HASH('T', 'F'):
+		/* typeinfo fn */
+		if (!DEM_PUSH_STR(ddata, "typeinfo fn for "))
+			return (0);
+		ddata->cur += 2;
+		if (*ddata->cur == '\0')
+			return (0);
+		return (cpp_demangle_read_type(ddata, NULL));
+
+	case SIMPLE_HASH('T', 'h'):
+		/* virtual function non-virtual override thunk */
+		if (!DEM_PUSH_STR(ddata,
+		    "virtual function non-virtual override "))
+			return (0);
+		ddata->cur += 2;
+		if (*ddata->cur == '\0')
+			return (0);
+		if (!cpp_demangle_read_nv_offset(ddata))
+			return (0);
+		return (cpp_demangle_read_encoding(ddata));
+
+	case SIMPLE_HASH('T', 'H'):
+		/* TLS init function */
+		if (!DEM_PUSH_STR(ddata, "TLS init function for "))
+			return (0);
+		ddata->cur += 2;
+		if (*ddata->cur == '\0')
+			return (0);
+		break;
+
+	case SIMPLE_HASH('T', 'I'):
+		/* typeinfo structure */
+		if (!DEM_PUSH_STR(ddata, "typeinfo for "))
+			return (0);
+		ddata->cur += 2;
+		if (*ddata->cur == '\0')
+			return (0);
+		return (cpp_demangle_read_type(ddata, NULL));
+
+	case SIMPLE_HASH('T', 'J'):
+		/* java class */
+		if (!DEM_PUSH_STR(ddata, "java Class for "))
+			return (0);
+		ddata->cur += 2;
+		if (*ddata->cur == '\0')
+			return (0);
+		return (cpp_demangle_read_type(ddata, NULL));
+
+	case SIMPLE_HASH('T', 'S'):
+		/* RTTI name (NTBS) */
+		if (!DEM_PUSH_STR(ddata, "typeinfo name for "))
+			return (0);
+		ddata->cur += 2;
+		if (*ddata->cur == '\0')
+			return (0);
+		return (cpp_demangle_read_type(ddata, NULL));
+
+	case SIMPLE_HASH('T', 'T'):
+		/* VTT table */
+		if (!DEM_PUSH_STR(ddata, "VTT for "))
+			return (0);
+		ddata->cur += 2;
+		if (*ddata->cur == '\0')
+			return (0);
+		return (cpp_demangle_read_type(ddata, NULL));
+
+	case SIMPLE_HASH('T', 'v'):
+		/* virtual function virtual override thunk */
+		if (!DEM_PUSH_STR(ddata, "virtual function virtual override "))
+			return (0);
+		ddata->cur += 2;
+		if (*ddata->cur == '\0')
+			return (0);
+		if (!cpp_demangle_read_v_offset(ddata))
+			return (0);
+		return (cpp_demangle_read_encoding(ddata));
+
+	case SIMPLE_HASH('T', 'V'):
+		/* virtual table */
+		if (!DEM_PUSH_STR(ddata, "vtable for "))
+			return (0);
+		ddata->cur += 2;
+		if (*ddata->cur == '\0')
+			return (0);
+		return (cpp_demangle_read_type(ddata, NULL));
+
+	case SIMPLE_HASH('T', 'W'):
+		/* TLS wrapper function */
+		if (!DEM_PUSH_STR(ddata, "TLS wrapper function for "))
+			return (0);
+		ddata->cur += 2;
+		if (*ddata->cur == '\0')
+			return (0);
+		break;
+	}
+
+	return (cpp_demangle_read_name(ddata));
+}
+
+static int
+cpp_demangle_read_local_name(struct cpp_demangle_data *ddata)
+{
+	struct vector_str local_name;
+	struct type_delimit td;
+	size_t limit;
+	bool  more_type;
+
+	if (ddata == NULL)
+		return (0);
+	if (*(++ddata->cur) == '\0')
+		return (0);
+
+	vector_str_init(&local_name);
+	ddata->cur_output = &local_name;
+
+	if (!cpp_demangle_read_encoding(ddata)) {
+		vector_str_dest(&local_name);
+		return (0);
+	}
+
+	ddata->cur_output = &ddata->output;
+
+	td.paren = false;
+	td.firstp = true;
+	more_type = false;
+	limit = 0;
+
+	/*
+	 * The first type is a return type if we just demangled template
+	 * args. (the template args is right next to the function name,
+	 * which means it's a template function)
+	 */
+	if (ddata->is_tmpl) {
+		ddata->is_tmpl = false;
+
+		/* Read return type */
+		if (!cpp_demangle_read_type(ddata, NULL)) {
+			vector_str_dest(&local_name);
+			return (0);
+		}
+
+		more_type = true;
+	}
+
+	/* Now we can push the name after possible return type is handled. */
+	if (!vector_str_push_vector(&ddata->output, &local_name)) {
+		vector_str_dest(&local_name);
+		return (0);
+	}
+	vector_str_dest(&local_name);
+
+	while (*ddata->cur != '\0') {
+		if (!cpp_demangle_read_type(ddata, &td))
+			return (0);
+		if (more_type)
+			more_type = false;
+		if (*ddata->cur == 'E')
+			break;
+		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
+			return (0);
+	}
+	if (more_type)
+		return (0);
+
+	if (*(++ddata->cur) == '\0')
+		return (0);
+	if (td.paren == true) {
+		if (!DEM_PUSH_STR(ddata, ")"))
+			return (0);
+		td.paren = false;
+	}
+	if (*ddata->cur == 's')
+		++ddata->cur;
+	else {
+		if (!DEM_PUSH_STR(ddata, "::"))
+			return (0);
+		if (!cpp_demangle_read_name(ddata))
+			return (0);
+	}
+	if (*ddata->cur == '_') {
+		++ddata->cur;
+		while (ELFTC_ISDIGIT(*ddata->cur) != 0)
+			++ddata->cur;
+	}
+
+	return (1);
+}
+
+static int
+cpp_demangle_read_name(struct cpp_demangle_data *ddata)
+{
+	struct vector_str *output, v;
+	size_t p_idx, subst_str_len;
+	int rtn;
+	char *subst_str;
+
+	if (ddata == NULL || *ddata->cur == '\0')
+		return (0);
+
+	output = ddata->cur_output;
+
+	subst_str = NULL;
+
+	switch (*ddata->cur) {
+	case 'S':
+		return (cpp_demangle_read_subst(ddata));
+	case 'N':
+		return (cpp_demangle_read_nested_name(ddata));
+	case 'Z':
+		return (cpp_demangle_read_local_name(ddata));
+	}
+
+	if (!vector_str_init(&v))
+		return (0);
+
+	p_idx = output->size;
+	rtn = 0;
+	if (!cpp_demangle_read_uqname(ddata))
+		goto clean;
+	if ((subst_str = vector_str_substr(output, p_idx, output->size - 1,
+	    &subst_str_len)) == NULL)
+		goto clean;
+	if (subst_str_len > 8 && strstr(subst_str, "operator") != NULL) {
+		rtn = 1;
+		goto clean;
+	}
+	if (!vector_str_push(&v, subst_str, subst_str_len))
+		goto clean;
+	if (!cpp_demangle_push_subst_v(ddata, &v))
+		goto clean;
+
+	if (*ddata->cur == 'I') {
+		p_idx = output->size;
+		if (!cpp_demangle_read_tmpl_args(ddata))
+			goto clean;
+		free(subst_str);
+		if ((subst_str = vector_str_substr(output, p_idx,
+		    output->size - 1, &subst_str_len)) == NULL)
+			goto clean;
+		if (!vector_str_push(&v, subst_str, subst_str_len))
+			goto clean;
+		if (!cpp_demangle_push_subst_v(ddata, &v))
+			goto clean;
+	}
+
+	rtn = 1;
+
+clean:
+	free(subst_str);
+	vector_str_dest(&v);
+
+	return (rtn);
+}
+
+static int
+cpp_demangle_read_name_flat(struct cpp_demangle_data *ddata, char **str)
+{
+	struct vector_str *output;
+	size_t i, p_idx, idx, name_len;
+	char *name;
+
+	output = ddata->cur_output;
+
+	p_idx = output->size;
+
+	if (!cpp_demangle_read_name(ddata))
+		return (0);
+
+	if ((name = vector_str_substr(output, p_idx, output->size - 1,
+	    &name_len)) == NULL)
+		return (0);
+
+	idx = output->size;
+	for (i = p_idx; i < idx; ++i) {
+		if (!vector_str_pop(output)) {
+			free(name);
+			return (0);
+		}
+	}
+
+	*str = name;
+
+	return (1);
+}
+
+static int
+cpp_demangle_read_nested_name(struct cpp_demangle_data *ddata)
+{
+	struct vector_str *output, v;
+	size_t limit, p_idx, subst_str_len;
+	int rtn;
+	char *subst_str;
+
+	if (ddata == NULL || *ddata->cur != 'N')
+		return (0);
+	if (*(++ddata->cur) == '\0')
+		return (0);
+
+	do {
+		switch (*ddata->cur) {
+		case 'r':
+			ddata->mem_rst = true;
+			break;
+		case 'V':
+			ddata->mem_vat = true;
+			break;
+		case 'K':
+			ddata->mem_cst = true;
+			break;
+		case 'R':
+			ddata->mem_ref = true;
+			break;
+		case 'O':
+			ddata->mem_rref = true;
+			break;
+		default:
+			goto next;
+		}
+	} while (*(++ddata->cur));
+
+next:
+	output = ddata->cur_output;
+	if (!vector_str_init(&v))
+		return (0);
+
+	rtn = 0;
+	limit = 0;
+	for (;;) {
+		p_idx = output->size;
+		switch (*ddata->cur) {
+		case 'I':
+			if (!cpp_demangle_read_tmpl_args(ddata))
+				goto clean;
+			break;
+		case 'S':
+			if (!cpp_demangle_read_subst(ddata))
+				goto clean;
+			break;
+		case 'T':
+			if (!cpp_demangle_read_tmpl_param(ddata))
+				goto clean;
+			break;
+		default:
+			if (!cpp_demangle_read_uqname(ddata))
+				goto clean;
+		}
+
+		if (p_idx == output->size)
+			goto next_comp;
+		if ((subst_str = vector_str_substr(output, p_idx,
+		    output->size - 1, &subst_str_len)) == NULL)
+			goto clean;
+		if (!vector_str_push(&v, subst_str, subst_str_len)) {
+			free(subst_str);
+			goto clean;
+		}
+		free(subst_str);
+
+		if (!cpp_demangle_push_subst_v(ddata, &v))
+			goto clean;
+
+	next_comp:
+		if (*ddata->cur == 'E')
+			break;
+		else if (*ddata->cur != 'I' && *ddata->cur != 'C' &&
+		    *ddata->cur != 'D' && p_idx != output->size) {
+			if (!DEM_PUSH_STR(ddata, "::"))
+				goto clean;
+			if (!VEC_PUSH_STR(&v, "::"))
+				goto clean;
+		}
+		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
+			goto clean;
+	}
+
+	++ddata->cur;
+	rtn = 1;
+
+clean:
+	vector_str_dest(&v);
+
+	return (rtn);
+}
+
+/*
+ * read number
+ * number ::= [n] <decimal>
+ */
+static int
+cpp_demangle_read_number(struct cpp_demangle_data *ddata, long *rtn)
+{
+	long len, negative_factor;
+
+	if (ddata == NULL || rtn == NULL)
+		return (0);
+
+	negative_factor = 1;
+	if (*ddata->cur == 'n') {
+		negative_factor = -1;
+
+		++ddata->cur;
+	}
+	if (ELFTC_ISDIGIT(*ddata->cur) == 0)
+		return (0);
+
+	errno = 0;
+	if ((len = strtol(ddata->cur, (char **) NULL, 10)) == 0 &&
+	    errno != 0)
+		return (0);
+
+	while (ELFTC_ISDIGIT(*ddata->cur) != 0)
+		++ddata->cur;
+
+	assert(len >= 0);
+	assert(negative_factor == 1 || negative_factor == -1);
+
+	*rtn = len * negative_factor;
+
+	return (1);
+}
+
+static int
+cpp_demangle_read_number_as_string(struct cpp_demangle_data *ddata, char **str)
+{
+	long n;
+
+	if (!cpp_demangle_read_number(ddata, &n)) {
+		*str = NULL;
+		return (0);
+	}
+
+	if (asprintf(str, "%ld", n) < 0) {
+		*str = NULL;
+		return (0);
+	}
+
+	return (1);
+}
+
+static int
+cpp_demangle_read_nv_offset(struct cpp_demangle_data *ddata)
+{
+
+	if (ddata == NULL)
+		return (0);
+
+	if (!DEM_PUSH_STR(ddata, "offset : "))
+		return (0);
+
+	return (cpp_demangle_read_offset_number(ddata));
+}
+
+/* read offset, offset are nv-offset, v-offset */
+static int
+cpp_demangle_read_offset(struct cpp_demangle_data *ddata)
+{
+
+	if (ddata == NULL)
+		return (0);
+
+	if (*ddata->cur == 'h') {
+		++ddata->cur;
+		return (cpp_demangle_read_nv_offset(ddata));
+	} else if (*ddata->cur == 'v') {
+		++ddata->cur;
+		return (cpp_demangle_read_v_offset(ddata));
+	}
+
+	return (0);
+}
+
+static int
+cpp_demangle_read_offset_number(struct cpp_demangle_data *ddata)
+{
+	bool negative;
+	const char *start;
+
+	if (ddata == NULL || *ddata->cur == '\0')
+		return (0);
+
+	/* offset could be negative */
+	if (*ddata->cur == 'n') {
+		negative = true;
+		start = ddata->cur + 1;
+	} else {
+		negative = false;
+		start = ddata->cur;
+	}
+
+	while (*ddata->cur != '_')
+		++ddata->cur;
+
+	if (negative && !DEM_PUSH_STR(ddata, "-"))
+		return (0);
+
+	assert(start != NULL);
+
+	if (!cpp_demangle_push_str(ddata, start, ddata->cur - start))
+		return (0);
+	if (!DEM_PUSH_STR(ddata, " "))
+		return (0);
+
+	++ddata->cur;
+
+	return (1);
+}
+
+static int
+cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *ddata,
+    struct vector_type_qualifier *v)
+{
+	size_t class_type_len, i, idx, p_idx;
+	int p_func_type, rtn;
+	char *class_type;
+
+	if (ddata == NULL || *ddata->cur != 'M' || *(++ddata->cur) == '\0')
+		return (0);
+
+	p_idx = ddata->output.size;
+	if (!cpp_demangle_read_type(ddata, NULL))
+		return (0);
+
+	if ((class_type = vector_str_substr(&ddata->output, p_idx,
+	    ddata->output.size - 1, &class_type_len)) == NULL)
+		return (0);
+
+	rtn = 0;
+	idx = ddata->output.size;
+	for (i = p_idx; i < idx; ++i)
+		if (!vector_str_pop(&ddata->output))
+			goto clean1;
+
+	if (!vector_read_cmd_push(&ddata->cmd, READ_PTRMEM, v))
+		goto clean1;
+
+	if (!vector_str_push(&ddata->class_type, class_type, class_type_len))
+		goto clean2;
+
+	p_func_type = ddata->func_type;
+	if (!cpp_demangle_read_type(ddata, NULL))
+		goto clean3;
+
+	if (p_func_type == ddata->func_type) {
+		if (!DEM_PUSH_STR(ddata, " "))
+			goto clean3;
+		if (!cpp_demangle_push_str(ddata, class_type, class_type_len))
+			goto clean3;
+		if (!DEM_PUSH_STR(ddata, "::*"))
+			goto clean3;
+	}
+
+	rtn = 1;
+clean3:
+	if (!vector_str_pop(&ddata->class_type))
+		rtn = 0;
+clean2:
+	if (!vector_read_cmd_pop(&ddata->cmd))
+		rtn = 0;
+clean1:
+	free(class_type);
+
+	vector_type_qualifier_dest(v);
+	if (!vector_type_qualifier_init(v))
+		return (0);
+
+	return (rtn);
+}
+
+/* read source-name, source-name is <len> <ID> */
+static int
+cpp_demangle_read_sname(struct cpp_demangle_data *ddata)
+{
+	long len;
+	int err;
+
+	if (ddata == NULL || cpp_demangle_read_number(ddata, &len) == 0 ||
+	    len <= 0)
+		return (0);
+
+	if (len == 12 && (memcmp("_GLOBAL__N_1", ddata->cur, 12) == 0))
+		err = DEM_PUSH_STR(ddata, "(anonymous namespace)");
+	else
+		err = cpp_demangle_push_str(ddata, ddata->cur, len);
+
+	if (err == 0)
+		return (0);
+
+	assert(ddata->output.size > 0);
+	if (vector_read_cmd_find(&ddata->cmd, READ_TMPL) == NULL)
+		ddata->last_sname =
+		    ddata->output.container[ddata->output.size - 1];
+
+	ddata->cur += len;
+
+	return (1);
+}
+
+static int
+cpp_demangle_read_subst(struct cpp_demangle_data *ddata)
+{
+	long nth;
+
+	if (ddata == NULL || *ddata->cur == '\0')
+		return (0);
+
+	/* abbreviations of the form Sx */
+	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
+	case SIMPLE_HASH('S', 'a'):
+		/* std::allocator */
+		if (!DEM_PUSH_STR(ddata, "std::allocator"))
+			return (0);
+		ddata->cur += 2;
+		if (*ddata->cur == 'I')
+			return (cpp_demangle_read_subst_stdtmpl(ddata,
+			    "std::allocator"));
+		return (1);
+
+	case SIMPLE_HASH('S', 'b'):
+		/* std::basic_string */
+		if (!DEM_PUSH_STR(ddata, "std::basic_string"))
+			return (0);
+		ddata->cur += 2;
+		if (*ddata->cur == 'I')
+			return (cpp_demangle_read_subst_stdtmpl(ddata,
+			    "std::basic_string"));
+		return (1);
+
+	case SIMPLE_HASH('S', 'd'):
+		/* std::basic_iostream<char, std::char_traits<char> > */
+		if (!DEM_PUSH_STR(ddata, "std::basic_iostream<char, "
+		    "std::char_traits<char> >"))
+			return (0);
+		ddata->last_sname = "basic_iostream";
+		ddata->cur += 2;
+		if (*ddata->cur == 'I')
+			return (cpp_demangle_read_subst_stdtmpl(ddata,
+			    "std::basic_iostream<char, std::char_traits"
+				"<char> >"));
+		return (1);
+
+	case SIMPLE_HASH('S', 'i'):
+		/* std::basic_istream<char, std::char_traits<char> > */
+		if (!DEM_PUSH_STR(ddata, "std::basic_istream<char, "
+		    "std::char_traits<char> >"))
+			return (0);
+		ddata->last_sname = "basic_istream";
+		ddata->cur += 2;
+		if (*ddata->cur == 'I')
+			return (cpp_demangle_read_subst_stdtmpl(ddata,
+			    "std::basic_istream<char, std::char_traits"
+				"<char> >"));
+		return (1);
+
+	case SIMPLE_HASH('S', 'o'):
+		/* std::basic_ostream<char, std::char_traits<char> > */
+		if (!DEM_PUSH_STR(ddata, "std::basic_ostream<char, "
+		    "std::char_traits<char> >"))
+			return (0);
+		ddata->last_sname = "basic_ostream";
+		ddata->cur += 2;
+		if (*ddata->cur == 'I')
+			return (cpp_demangle_read_subst_stdtmpl(ddata,
+			    "std::basic_ostream<char, std::char_traits"
+				"<char> >"));
+		return (1);
+
+	case SIMPLE_HASH('S', 's'):
+		/*
+		 * std::basic_string<char, std::char_traits<char>,
+		 * std::allocator<char> >
+		 *
+		 * a.k.a std::string
+		 */
+		if (!DEM_PUSH_STR(ddata, "std::basic_string<char, "
+		    "std::char_traits<char>, std::allocator<char> >"))
+			return (0);
+		ddata->last_sname = "string";
+		ddata->cur += 2;
+		if (*ddata->cur == 'I')
+			return (cpp_demangle_read_subst_stdtmpl(ddata,
+			    "std::basic_string<char, std::char_traits<char>,"
+				" std::allocator<char> >"));
+		return (1);
+
+	case SIMPLE_HASH('S', 't'):
+		/* std:: */
+		return (cpp_demangle_read_subst_std(ddata));
+	}
+
+	if (*(++ddata->cur) == '\0')
+		return (0);
+
+	/* Skip unknown substitution abbreviations. */
+	if (!(*ddata->cur >= '0' && *ddata->cur <= '9') &&
+	    !(*ddata->cur >= 'A' && *ddata->cur <= 'Z') &&
+	    *ddata->cur != '_') {
+		++ddata->cur;
+		return (1);
+	}
+
+	/* substitution */
+	if (*ddata->cur == '_')
+		return (cpp_demangle_get_subst(ddata, 0));
+	else {
+		errno = 0;
+		/* substitution number is base 36 */
+		if ((nth = strtol(ddata->cur, (char **) NULL, 36)) == 0 &&
+		    errno != 0)
+			return (0);
+
+		/* first was '_', so increase one */
+		++nth;
+
+		while (*ddata->cur != '_')
+			++ddata->cur;
+
+		assert(nth > 0);
+
+		return (cpp_demangle_get_subst(ddata, nth));
+	}
+
+	/* NOTREACHED */
+	return (0);
+}
+
+static int
+cpp_demangle_read_subst_std(struct cpp_demangle_data *ddata)
+{
+	struct vector_str *output, v;
+	size_t p_idx, subst_str_len;
+	int rtn;
+	char *subst_str;
+
+	if (ddata == NULL)
+		return (0);
+
+	if (!vector_str_init(&v))
+		return (0);
+
+	subst_str = NULL;
+	rtn = 0;
+	if (!DEM_PUSH_STR(ddata, "std::"))
+		goto clean;
+
+	if (!VEC_PUSH_STR(&v, "std::"))
+		goto clean;
+
+	ddata->cur += 2;
+
+	output = ddata->cur_output;
+
+	p_idx = output->size;
+	if (!cpp_demangle_read_uqname(ddata))
+		goto clean;
+
+	if ((subst_str = vector_str_substr(output, p_idx, output->size - 1,
+	    &subst_str_len)) == NULL)
+		goto clean;
+
+	if (!vector_str_push(&v, subst_str, subst_str_len))
+		goto clean;
+
+	if (!cpp_demangle_push_subst_v(ddata, &v))
+		goto clean;
+
+	if (*ddata->cur == 'I') {
+		p_idx = output->size;
+		if (!cpp_demangle_read_tmpl_args(ddata))
+			goto clean;
+		free(subst_str);
+		if ((subst_str = vector_str_substr(output, p_idx,
+		    output->size - 1, &subst_str_len)) == NULL)
+			goto clean;
+		if (!vector_str_push(&v, subst_str, subst_str_len))
+			goto clean;
+		if (!cpp_demangle_push_subst_v(ddata, &v))
+			goto clean;
+	}
+
+	rtn = 1;
+clean:
+	free(subst_str);
+	vector_str_dest(&v);
+
+	return (rtn);
+}
+
+static int
+cpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data *ddata,
+    const char *str)
+{
+	struct vector_str *output;
+	size_t p_idx, substr_len, len;
+	int rtn;
+	char *subst_str, *substr;
+
+	if (ddata == NULL || str == NULL)
+		return (0);
+
+	if ((len = strlen(str)) == 0)
+		return (0);
+
+	output = ddata->cur_output;
+
+	p_idx = output->size;
+	substr = NULL;
+	subst_str = NULL;
+
+	if (!cpp_demangle_read_tmpl_args(ddata))
+		return (0);
+	if ((substr = vector_str_substr(output, p_idx, output->size - 1,
+	    &substr_len)) == NULL)
+		return (0);
+
+	rtn = 0;
+	if ((subst_str = malloc(sizeof(char) * (substr_len + len + 1))) ==
+	    NULL)
+		goto clean;
+
+	memcpy(subst_str, str, len);
+	memcpy(subst_str + len, substr, substr_len);
+	subst_str[substr_len + len] = '\0';
+
+	if (!cpp_demangle_push_subst(ddata, subst_str, substr_len + len))
+		goto clean;
+
+	rtn = 1;
+clean:
+	free(subst_str);
+	free(substr);
+
+	return (rtn);
+}
+
+static int
+cpp_demangle_read_tmpl_arg(struct cpp_demangle_data *ddata)
+{
+
+	if (ddata == NULL || *ddata->cur == '\0')
+		return (0);
+
+	switch (*ddata->cur) {
+	case 'L':
+		return (cpp_demangle_read_expr_primary(ddata));
+	case 'X':
+		++ddata->cur;
+		if (!cpp_demangle_read_expression(ddata))
+			return (0);
+		return (*ddata->cur++ == 'E');
+	}
+
+	return (cpp_demangle_read_type(ddata, NULL));
+}
+
+static int
+cpp_demangle_read_tmpl_args(struct cpp_demangle_data *ddata)
+{
+	struct vector_str *v;
+	size_t arg_len, idx, limit, size;
+	char *arg;
+
+	if (ddata == NULL || *ddata->cur == '\0')
+		return (0);
+
+	++ddata->cur;
+
+	if (!vector_read_cmd_push(&ddata->cmd, READ_TMPL, NULL))
+		return (0);
+
+	if (!DEM_PUSH_STR(ddata, "<"))
+		return (0);
+
+	limit = 0;
+	v = &ddata->output;
+	for (;;) {
+		idx = v->size;
+		if (!cpp_demangle_read_tmpl_arg(ddata))
+			return (0);
+		if ((arg = vector_str_substr(v, idx, v->size - 1, &arg_len)) ==
+		    NULL)
+			return (0);
+		if (!vector_str_find(&ddata->tmpl, arg, arg_len) &&
+		    !vector_str_push(&ddata->tmpl, arg, arg_len)) {
+			free(arg);
+			return (0);
+		}
+
+		free(arg);
+
+		if (*ddata->cur == 'E') {
+			++ddata->cur;
+			size = v->size;
+			assert(size > 0);
+			if (!strncmp(v->container[size - 1], ">", 1)) {
+				if (!DEM_PUSH_STR(ddata, " >"))
+					return (0);
+			} else if (!DEM_PUSH_STR(ddata, ">"))
+				return (0);
+			ddata->is_tmpl = true;
+			break;
+		} else if (*ddata->cur != 'I' &&
+		    !DEM_PUSH_STR(ddata, ", "))
+			return (0);
+
+		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
+			return (0);
+	}
+
+	return (vector_read_cmd_pop(&ddata->cmd));
+}
+
+/*
+ * Read template parameter that forms in 'T[number]_'.
+ * This function much like to read_subst but only for types.
+ */
+static int
+cpp_demangle_read_tmpl_param(struct cpp_demangle_data *ddata)
+{
+	long nth;
+
+	if (ddata == NULL || *ddata->cur != 'T')
+		return (0);
+
+	++ddata->cur;
+
+	if (*ddata->cur == '_')
+		return (cpp_demangle_get_tmpl_param(ddata, 0));
+	else {
+
+		errno = 0;
+		if ((nth = strtol(ddata->cur, (char **) NULL, 36)) == 0 &&
+		    errno != 0)
+			return (0);
+
+		/* T_ is first */
+		++nth;
+
+		while (*ddata->cur != '_')
+			++ddata->cur;
+
+		assert(nth > 0);
+
+		return (cpp_demangle_get_tmpl_param(ddata, nth));
+	}
+
+	/* NOTREACHED */
+	return (0);
+}
+
+static int
+cpp_demangle_read_type(struct cpp_demangle_data *ddata,
+    struct type_delimit *td)
+{
+	struct vector_type_qualifier v;
+	struct vector_str *output, sv;
+	size_t p_idx, type_str_len, subst_str_len;
+	int extern_c, is_builtin;
+	long len;
+	const char *p;
+	char *type_str, *exp_str, *num_str, *subst_str;
+	bool skip_ref_qualifier, omit_void;
+
+	if (ddata == NULL)
+		return (0);
+
+	output = ddata->cur_output;
+	if (td) {
+		if (td->paren == false) {
+			if (!DEM_PUSH_STR(ddata, "("))
+				return (0);
+			if (ddata->output.size < 2)
+				return (0);
+			td->paren = true;
+		}
+
+		if (!td->firstp) {
+			if (*ddata->cur != 'I') {
+				if (!DEM_PUSH_STR(ddata, ", "))
+					return (0);
+			}
+		}
+	}
+
+	assert(output != NULL);
+	/*
+	 * [r, V, K] [P, R, O, C, G, U] builtin, function, class-enum, array
+	 * pointer-to-member, template-param, template-template-param, subst
+	 */
+
+	if (!vector_type_qualifier_init(&v))
+		return (0);
+
+	extern_c = 0;
+	is_builtin = 1;
+	p_idx = output->size;
+	type_str = exp_str = num_str = NULL;
+	skip_ref_qualifier = false;
+
+again:
+
+	/* Clear ref-qualifier flag */
+	if (*ddata->cur != 'R' && *ddata->cur != 'O' && *ddata->cur != 'E')
+		ddata->ref_qualifier = false;
+
+	/* builtin type */
+	switch (*ddata->cur) {
+	case 'a':
+		/* signed char */
+		if (!DEM_PUSH_STR(ddata, "signed char"))
+			goto clean;
+		++ddata->cur;
+		goto rtn;
+
+	case 'A':
+		/* array type */
+		if (!cpp_demangle_read_array(ddata))
+			goto clean;
+		is_builtin = 0;
+		goto rtn;
+
+	case 'b':
+		/* bool */
+		if (!DEM_PUSH_STR(ddata, "bool"))
+			goto clean;
+		++ddata->cur;
+		goto rtn;
+
+	case 'C':
+		/* complex pair */
+		if (!vector_type_qualifier_push(&v, TYPE_CMX))
+			goto clean;
+		++ddata->cur;
+		if (td)
+			td->firstp = false;
+		goto again;
+
+	case 'c':
+		/* char */
+		if (!DEM_PUSH_STR(ddata, "char"))
+			goto clean;
+		++ddata->cur;
+		goto rtn;
+
+	case 'd':
+		/* double */
+		if (!DEM_PUSH_STR(ddata, "double"))
+			goto clean;
+		++ddata->cur;
+		goto rtn;
+
+	case 'D':
+		++ddata->cur;
+		switch (*ddata->cur) {
+		case 'a':
+			/* auto */
+			if (!DEM_PUSH_STR(ddata, "auto"))
+				goto clean;
+			++ddata->cur;
+			break;
+		case 'c':
+			/* decltype(auto) */
+			if (!DEM_PUSH_STR(ddata, "decltype(auto)"))
+				goto clean;
+			++ddata->cur;
+			break;
+		case 'd':
+			/* IEEE 754r decimal floating point (64 bits) */
+			if (!DEM_PUSH_STR(ddata, "decimal64"))
+				goto clean;
+			++ddata->cur;
+			break;
+		case 'e':
+			/* IEEE 754r decimal floating point (128 bits) */
+			if (!DEM_PUSH_STR(ddata, "decimal128"))
+				goto clean;
+			++ddata->cur;
+			break;
+		case 'f':
+			/* IEEE 754r decimal floating point (32 bits) */
+			if (!DEM_PUSH_STR(ddata, "decimal32"))
+				goto clean;
+			++ddata->cur;
+			break;
+		case 'h':
+			/* IEEE 754r half-precision floating point (16 bits) */
+			if (!DEM_PUSH_STR(ddata, "half"))
+				goto clean;
+			++ddata->cur;
+			break;
+		case 'i':
+			/* char32_t */
+			if (!DEM_PUSH_STR(ddata, "char32_t"))
+				goto clean;
+			++ddata->cur;
+			break;
+		case 'n':
+			/* std::nullptr_t (i.e., decltype(nullptr)) */
+			if (!DEM_PUSH_STR(ddata, "decltype(nullptr)"))
+				goto clean;
+			++ddata->cur;
+			break;
+		case 's':
+			/* char16_t */
+			if (!DEM_PUSH_STR(ddata, "char16_t"))
+				goto clean;
+			++ddata->cur;
+			break;
+		case 'v':
+			/* gcc vector_size extension. */
+			++ddata->cur;
+			if (*ddata->cur == '_') {
+				++ddata->cur;
+				if (!cpp_demangle_read_expression_flat(ddata,
+				    &exp_str))
+					goto clean;
+				if (!VEC_PUSH_STR(&v.ext_name, exp_str))
+					goto clean;
+			} else {
+				if (!cpp_demangle_read_number_as_string(ddata,
+				    &num_str))
+					goto clean;
+				if (!VEC_PUSH_STR(&v.ext_name, num_str))
+					goto clean;
+			}
+			if (*ddata->cur != '_')
+				goto clean;
+			++ddata->cur;
+			if (!vector_type_qualifier_push(&v, TYPE_VEC))
+				goto clean;
+			if (td)
+				td->firstp = false;
+			goto again;
+		default:
+			goto clean;
+		}
+		goto rtn;
+
+	case 'e':
+		/* long double */
+		if (!DEM_PUSH_STR(ddata, "long double"))
+			goto clean;
+		++ddata->cur;
+		goto rtn;
+
+	case 'E':
+		/* unexpected end except ref-qualifiers */
+		if (ddata->ref_qualifier && ddata->is_functype) {
+			skip_ref_qualifier = true;
+			/* Pop the delimiter. */
+			cpp_demangle_pop_str(ddata);
+			goto rtn;
+		}
+		goto clean;
+
+	case 'f':
+		/* float */
+		if (!DEM_PUSH_STR(ddata, "float"))
+			goto clean;
+		++ddata->cur;
+		goto rtn;
+
+	case 'F':
+		/* function */
+		if (!cpp_demangle_read_function(ddata, &extern_c, &v))
+			goto clean;
+		is_builtin = 0;
+		goto rtn;
+
+	case 'g':
+		/* __float128 */
+		if (!DEM_PUSH_STR(ddata, "__float128"))
+			goto clean;
+		++ddata->cur;
+		goto rtn;
+
+	case 'G':
+		/* imaginary */
+		if (!vector_type_qualifier_push(&v, TYPE_IMG))
+			goto clean;
+		++ddata->cur;
+		if (td)
+			td->firstp = false;
+		goto again;
+
+	case 'h':
+		/* unsigned char */
+		if (!DEM_PUSH_STR(ddata, "unsigned char"))
+			goto clean;
+		++ddata->cur;
+		goto rtn;
+
+	case 'i':
+		/* int */
+		if (!DEM_PUSH_STR(ddata, "int"))
+			goto clean;
+		++ddata->cur;
+		goto rtn;
+
+	case 'I':
+		/* template args. */
+		/* handles <substitute><template-args> */
+		p_idx = output->size;
+		if (!cpp_demangle_read_tmpl_args(ddata))
+			goto clean;
+		if ((subst_str = vector_str_substr(output, p_idx,
+		    output->size - 1, &subst_str_len)) == NULL)
+			goto clean;
+		if (!vector_str_init(&sv)) {
+			free(subst_str);
+			goto clean;
+		}
+		if (!vector_str_push(&sv, subst_str, subst_str_len)) {
+			free(subst_str);
+			vector_str_dest(&sv);
+			goto clean;
+		}
+		free(subst_str);
+		if (!cpp_demangle_push_subst_v(ddata, &sv)) {
+			vector_str_dest(&sv);
+			goto clean;
+		}
+		vector_str_dest(&sv);
+		goto rtn;
+
+	case 'j':
+		/* unsigned int */
+		if (!DEM_PUSH_STR(ddata, "unsigned int"))
+			goto clean;
+		++ddata->cur;
+		goto rtn;
+
+	case 'K':
+		/* const */
+		if (!vector_type_qualifier_push(&v, TYPE_CST))
+			goto clean;
+		++ddata->cur;
+		if (td)
+			td->firstp = false;
+		goto again;
+
+	case 'l':
+		/* long */
+		if (!DEM_PUSH_STR(ddata, "long"))
+			goto clean;
+		++ddata->cur;
+		goto rtn;
+
+	case 'm':
+		/* unsigned long */
+		if (!DEM_PUSH_STR(ddata, "unsigned long"))
+			goto clean;
+
+		++ddata->cur;
+
+		goto rtn;
+	case 'M':
+		/* pointer to member */
+		if (!cpp_demangle_read_pointer_to_member(ddata, &v))
+			goto clean;
+		is_builtin = 0;
+		goto rtn;
+
+	case 'n':
+		/* __int128 */
+		if (!DEM_PUSH_STR(ddata, "__int128"))
+			goto clean;
+		++ddata->cur;
+		goto rtn;
+
+	case 'o':
+		/* unsigned __int128 */
+		if (!DEM_PUSH_STR(ddata, "unsigned __int128"))
+			goto clean;
+		++ddata->cur;
+		goto rtn;
+
+	case 'O':
+		/* rvalue reference */
+		if (ddata->ref_qualifier)
+			goto clean;
+		if (!vector_type_qualifier_push(&v, TYPE_RREF))
+			goto clean;
+		ddata->ref_qualifier = true;
+		ddata->ref_qualifier_type = TYPE_RREF;
+		++ddata->cur;
+		if (td)
+			td->firstp = false;
+		goto again;
+
+	case 'P':
+		/* pointer */
+		if (!vector_type_qualifier_push(&v, TYPE_PTR))
+			goto clean;
+		++ddata->cur;
+		if (td)
+			td->firstp = false;
+		goto again;
+
+	case 'r':
+		/* restrict */
+		if (!vector_type_qualifier_push(&v, TYPE_RST))
+			goto clean;
+		++ddata->cur;
+		if (td)
+			td->firstp = false;
+		goto again;
+
+	case 'R':
+		/* reference */
+		if (ddata->ref_qualifier)
+			goto clean;
+		if (!vector_type_qualifier_push(&v, TYPE_REF))
+			goto clean;
+		ddata->ref_qualifier = true;
+		ddata->ref_qualifier_type = TYPE_REF;
+		++ddata->cur;
+		if (td)
+			td->firstp = false;
+		goto again;
+
+	case 's':
+		/* short, local string */
+		if (!DEM_PUSH_STR(ddata, "short"))
+			goto clean;
+		++ddata->cur;
+		goto rtn;
+
+	case 'S':
+		/* substitution */
+		if (!cpp_demangle_read_subst(ddata))
+			goto clean;
+		is_builtin = 0;
+		goto rtn;
+
+	case 't':
+		/* unsigned short */
+		if (!DEM_PUSH_STR(ddata, "unsigned short"))
+			goto clean;
+		++ddata->cur;
+		goto rtn;
+
+	case 'T':
+		/* template parameter */
+		if (!cpp_demangle_read_tmpl_param(ddata))
+			goto clean;
+		is_builtin = 0;
+		goto rtn;
+
+	case 'u':
+		/* vendor extended builtin */
+		++ddata->cur;
+		if (!cpp_demangle_read_sname(ddata))
+			goto clean;
+		is_builtin = 0;
+		goto rtn;
+
+	case 'U':
+		/* vendor extended type qualifier */
+		++ddata->cur;
+		if (!cpp_demangle_read_number(ddata, &len))
+			goto clean;
+		if (len <= 0)
+			goto clean;
+		if (!vector_str_push(&v.ext_name, ddata->cur, len))
+			return (0);
+		ddata->cur += len;
+		if (!vector_type_qualifier_push(&v, TYPE_EXT))
+			goto clean;
+		if (td)
+			td->firstp = false;
+		goto again;
+
+	case 'v':
+		/* void */
+		omit_void = false;
+		if (td && td->firstp) {
+			/*
+			 * peek into next bytes and see if we should omit
+			 * the "void".
+			 */
+			omit_void = true;
+			for (p = ddata->cur + 1; *p != '\0'; p++) {
+				if (*p == 'E')
+					break;
+				if (*p != 'R' && *p != 'O') {
+					omit_void = false;
+					break;
+				}
+			}
+		}
+		if (!omit_void && !DEM_PUSH_STR(ddata, "void"))
+			goto clean;
+		++ddata->cur;
+		goto rtn;
+
+	case 'V':
+		/* volatile */
+		if (!vector_type_qualifier_push(&v, TYPE_VAT))
+			goto clean;
+		++ddata->cur;
+		if (td)
+			td->firstp = false;
+		goto again;
+
+	case 'w':
+		/* wchar_t */
+		if (!DEM_PUSH_STR(ddata, "wchar_t"))
+			goto clean;
+		++ddata->cur;
+		goto rtn;
+
+	case 'x':
+		/* long long */
+		if (!DEM_PUSH_STR(ddata, "long long"))
+			goto clean;
+		++ddata->cur;
+		goto rtn;
+
+	case 'y':
+		/* unsigned long long */
+		if (!DEM_PUSH_STR(ddata, "unsigned long long"))
+			goto clean;
+		++ddata->cur;
+		goto rtn;
+
+	case 'z':
+		/* ellipsis */
+		if (!DEM_PUSH_STR(ddata, "..."))
+			goto clean;
+		++ddata->cur;
+		goto rtn;
+	}
+
+	if (!cpp_demangle_read_name(ddata))
+		goto clean;
+
+	is_builtin = 0;
+rtn:
+
+	type_str = vector_str_substr(output, p_idx, output->size - 1,
+	    &type_str_len);
+
+	if (is_builtin == 0) {
+		if (!vector_str_find(&ddata->subst, type_str, type_str_len) &&
+		    !vector_str_push(&ddata->subst, type_str, type_str_len))
+			goto clean;
+	}
+
+	if (!skip_ref_qualifier &&
+	    !cpp_demangle_push_type_qualifier(ddata, &v, type_str))
+		goto clean;
+
+	if (td)
+		td->firstp = false;
+
+	free(type_str);
+	free(exp_str);
+	free(num_str);
+	vector_type_qualifier_dest(&v);
+
+	return (1);
+clean:
+	free(type_str);
+	free(exp_str);
+	free(num_str);
+	vector_type_qualifier_dest(&v);
+
+	return (0);
+}
+
+static int
+cpp_demangle_read_type_flat(struct cpp_demangle_data *ddata, char **str)
+{
+	struct vector_str *output;
+	size_t i, p_idx, idx, type_len;
+	char *type;
+
+	output = ddata->cur_output;
+
+	p_idx = output->size;
+
+	if (!cpp_demangle_read_type(ddata, NULL))
+		return (0);
+
+	if ((type = vector_str_substr(output, p_idx, output->size - 1,
+	    &type_len)) == NULL)
+		return (0);
+
+	idx = output->size;
+	for (i = p_idx; i < idx; ++i) {
+		if (!vector_str_pop(output)) {
+			free(type);
+			return (0);
+		}
+	}
+
+	*str = type;
+
+	return (1);
+}
+
+/*
+ * read unqualified-name, unqualified name are operator-name, ctor-dtor-name,
+ * source-name
+ */
+static int
+cpp_demangle_read_uqname(struct cpp_demangle_data *ddata)
+{
+	size_t len;
+
+	if (ddata == NULL || *ddata->cur == '\0')
+		return (0);
+
+	/* operator name */
+	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
+	case SIMPLE_HASH('a', 'a'):
+		/* operator && */
+		if (!DEM_PUSH_STR(ddata, "operator&&"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('a', 'd'):
+		/* operator & (unary) */
+		if (!DEM_PUSH_STR(ddata, "operator&"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('a', 'n'):
+		/* operator & */
+		if (!DEM_PUSH_STR(ddata, "operator&"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('a', 'N'):
+		/* operator &= */
+		if (!DEM_PUSH_STR(ddata, "operator&="))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('a', 'S'):
+		/* operator = */
+		if (!DEM_PUSH_STR(ddata, "operator="))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('c', 'l'):
+		/* operator () */
+		if (!DEM_PUSH_STR(ddata, "operator()"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('c', 'm'):
+		/* operator , */
+		if (!DEM_PUSH_STR(ddata, "operator,"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('c', 'o'):
+		/* operator ~ */
+		if (!DEM_PUSH_STR(ddata, "operator~"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('c', 'v'):
+		/* operator (cast) */
+		if (!DEM_PUSH_STR(ddata, "operator(cast)"))
+			return (0);
+		ddata->cur += 2;
+		return (cpp_demangle_read_type(ddata, NULL));
+
+	case SIMPLE_HASH('d', 'a'):
+		/* operator delete [] */
+		if (!DEM_PUSH_STR(ddata, "operator delete []"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('d', 'e'):
+		/* operator * (unary) */
+		if (!DEM_PUSH_STR(ddata, "operator*"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('d', 'l'):
+		/* operator delete */
+		if (!DEM_PUSH_STR(ddata, "operator delete"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('d', 'v'):
+		/* operator / */
+		if (!DEM_PUSH_STR(ddata, "operator/"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('d', 'V'):
+		/* operator /= */
+		if (!DEM_PUSH_STR(ddata, "operator/="))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('e', 'o'):
+		/* operator ^ */
+		if (!DEM_PUSH_STR(ddata, "operator^"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('e', 'O'):
+		/* operator ^= */
+		if (!DEM_PUSH_STR(ddata, "operator^="))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('e', 'q'):
+		/* operator == */
+		if (!DEM_PUSH_STR(ddata, "operator=="))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('g', 'e'):
+		/* operator >= */
+		if (!DEM_PUSH_STR(ddata, "operator>="))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('g', 't'):
+		/* operator > */
+		if (!DEM_PUSH_STR(ddata, "operator>"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('i', 'x'):
+		/* operator [] */
+		if (!DEM_PUSH_STR(ddata, "operator[]"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('l', 'e'):
+		/* operator <= */
+		if (!DEM_PUSH_STR(ddata, "operator<="))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('l', 's'):
+		/* operator << */
+		if (!DEM_PUSH_STR(ddata, "operator<<"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('l', 'S'):
+		/* operator <<= */
+		if (!DEM_PUSH_STR(ddata, "operator<<="))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('l', 't'):
+		/* operator < */
+		if (!DEM_PUSH_STR(ddata, "operator<"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('m', 'i'):
+		/* operator - */
+		if (!DEM_PUSH_STR(ddata, "operator-"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('m', 'I'):
+		/* operator -= */
+		if (!DEM_PUSH_STR(ddata, "operator-="))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('m', 'l'):
+		/* operator * */
+		if (!DEM_PUSH_STR(ddata, "operator*"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('m', 'L'):
+		/* operator *= */
+		if (!DEM_PUSH_STR(ddata, "operator*="))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('m', 'm'):
+		/* operator -- */
+		if (!DEM_PUSH_STR(ddata, "operator--"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('n', 'a'):
+		/* operator new[] */
+		if (!DEM_PUSH_STR(ddata, "operator new []"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('n', 'e'):
+		/* operator != */
+		if (!DEM_PUSH_STR(ddata, "operator!="))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('n', 'g'):
+		/* operator - (unary) */
+		if (!DEM_PUSH_STR(ddata, "operator-"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('n', 't'):
+		/* operator ! */
+		if (!DEM_PUSH_STR(ddata, "operator!"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('n', 'w'):
+		/* operator new */
+		if (!DEM_PUSH_STR(ddata, "operator new"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('o', 'o'):
+		/* operator || */
+		if (!DEM_PUSH_STR(ddata, "operator||"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('o', 'r'):
+		/* operator | */
+		if (!DEM_PUSH_STR(ddata, "operator|"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('o', 'R'):
+		/* operator |= */
+		if (!DEM_PUSH_STR(ddata, "operator|="))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('p', 'l'):
+		/* operator + */
+		if (!DEM_PUSH_STR(ddata, "operator+"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('p', 'L'):
+		/* operator += */
+		if (!DEM_PUSH_STR(ddata, "operator+="))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('p', 'm'):
+		/* operator ->* */
+		if (!DEM_PUSH_STR(ddata, "operator->*"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('p', 'p'):
+		/* operator ++ */
+		if (!DEM_PUSH_STR(ddata, "operator++"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('p', 's'):
+		/* operator + (unary) */
+		if (!DEM_PUSH_STR(ddata, "operator+"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('p', 't'):
+		/* operator -> */
+		if (!DEM_PUSH_STR(ddata, "operator->"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('q', 'u'):
+		/* operator ? */
+		if (!DEM_PUSH_STR(ddata, "operator?"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('r', 'm'):
+		/* operator % */
+		if (!DEM_PUSH_STR(ddata, "operator%"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('r', 'M'):
+		/* operator %= */
+		if (!DEM_PUSH_STR(ddata, "operator%="))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('r', 's'):
+		/* operator >> */
+		if (!DEM_PUSH_STR(ddata, "operator>>"))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('r', 'S'):
+		/* operator >>= */
+		if (!DEM_PUSH_STR(ddata, "operator>>="))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('r', 'z'):
+		/* operator sizeof */
+		if (!DEM_PUSH_STR(ddata, "operator sizeof "))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('s', 'r'):
+		/* scope resolution operator */
+		if (!DEM_PUSH_STR(ddata, "scope resolution operator "))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+
+	case SIMPLE_HASH('s', 'v'):
+		/* operator sizeof */
+		if (!DEM_PUSH_STR(ddata, "operator sizeof "))
+			return (0);
+		ddata->cur += 2;
+		return (1);
+	}
+
+	/* vendor extened operator */
+	if (*ddata->cur == 'v' && ELFTC_ISDIGIT(*(ddata->cur + 1))) {
+		if (!DEM_PUSH_STR(ddata, "vendor extened operator "))
+			return (0);
+		if (!cpp_demangle_push_str(ddata, ddata->cur + 1, 1))
+			return (0);
+		ddata->cur += 2;
+		return (cpp_demangle_read_sname(ddata));
+	}
+
+	/* ctor-dtor-name */
+	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
+	case SIMPLE_HASH('C', '1'):
+	case SIMPLE_HASH('C', '2'):
+	case SIMPLE_HASH('C', '3'):
+		if (ddata->last_sname == NULL)
+			return (0);
+		if ((len = strlen(ddata->last_sname)) == 0)
+			return (0);
+		if (!DEM_PUSH_STR(ddata, "::"))
+			return (0);
+		if (!cpp_demangle_push_str(ddata, ddata->last_sname, len))
+			return (0);
+		ddata->cur +=2;
+		return (1);
+
+	case SIMPLE_HASH('D', '0'):
+	case SIMPLE_HASH('D', '1'):
+	case SIMPLE_HASH('D', '2'):
+		if (ddata->last_sname == NULL)
+			return (0);
+		if ((len = strlen(ddata->last_sname)) == 0)
+			return (0);
+		if (!DEM_PUSH_STR(ddata, "::~"))
+			return (0);
+		if (!cpp_demangle_push_str(ddata, ddata->last_sname, len))
+			return (0);
+		ddata->cur +=2;
+		return (1);
+	}
+
+	/* source name */
+	if (ELFTC_ISDIGIT(*ddata->cur) != 0)
+		return (cpp_demangle_read_sname(ddata));
+
+	/* local source name */
+	if (*ddata->cur == 'L')
+		return (cpp_demangle_local_source_name(ddata));
+
+	return (1);
+}
+
+/*
+ * Read local source name.
+ *
+ * References:
+ *   http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31775
+ *   http://gcc.gnu.org/viewcvs?view=rev&revision=124467
+ */
+static int
+cpp_demangle_local_source_name(struct cpp_demangle_data *ddata)
+{
+	/* L */
+	if (ddata == NULL || *ddata->cur != 'L')
+		return (0);
+	++ddata->cur;
+
+	/* source name */
+	if (!cpp_demangle_read_sname(ddata))
+		return (0);
+
+	/* discriminator */
+	if (*ddata->cur == '_') {
+		++ddata->cur;
+		while (ELFTC_ISDIGIT(*ddata->cur) != 0)
+			++ddata->cur;
+	}
+
+	return (1);
+}
+
+static int
+cpp_demangle_read_v_offset(struct cpp_demangle_data *ddata)
+{
+
+	if (ddata == NULL)
+		return (0);
+
+	if (!DEM_PUSH_STR(ddata, "offset : "))
+		return (0);
+
+	if (!cpp_demangle_read_offset_number(ddata))
+		return (0);
+
+	if (!DEM_PUSH_STR(ddata, "virtual offset : "))
+		return (0);
+
+	return (!cpp_demangle_read_offset_number(ddata));
+}
+
+/*
+ * Decode floating point representation to string
+ * Return new allocated string or NULL
+ *
+ * Todo
+ * Replace these functions to macro.
+ */
+static char *
+decode_fp_to_double(const char *p, size_t len)
+{
+	double f;
+	size_t rtn_len, limit, i;
+	int byte;
+	char *rtn;
+
+	if (p == NULL || len == 0 || len % 2 != 0 || len / 2 > sizeof(double))
+		return (NULL);
+
+	memset(&f, 0, sizeof(double));
+
+	for (i = 0; i < len / 2; ++i) {
+		byte = hex_to_dec(p[len - i * 2 - 1]) +
+		    hex_to_dec(p[len - i * 2 - 2]) * 16;
+
+		if (byte < 0 || byte > 255)
+			return (NULL);
+
+#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
+		((unsigned char *)&f)[i] = (unsigned char)(byte);
+#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
+		((unsigned char *)&f)[sizeof(double) - i - 1] =
+		    (unsigned char)(byte);
+#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
+	}
+
+	rtn_len = 64;
+	limit = 0;
+again:
+	if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
+		return (NULL);
+
+	if (snprintf(rtn, rtn_len, "%fld", f) >= (int)rtn_len) {
+		free(rtn);
+		if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
+			return (NULL);
+		rtn_len *= BUFFER_GROWFACTOR;
+		goto again;
+	}
+
+	return rtn;
+}
+
+static char *
+decode_fp_to_float(const char *p, size_t len)
+{
+	size_t i, rtn_len, limit;
+	float f;
+	int byte;
+	char *rtn;
+
+	if (p == NULL || len == 0 || len % 2 != 0 || len / 2 > sizeof(float))
+		return (NULL);
+
+	memset(&f, 0, sizeof(float));
+
+	for (i = 0; i < len / 2; ++i) {
+		byte = hex_to_dec(p[len - i * 2 - 1]) +
+		    hex_to_dec(p[len - i * 2 - 2]) * 16;
+		if (byte < 0 || byte > 255)
+			return (NULL);
+#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
+		((unsigned char *)&f)[i] = (unsigned char)(byte);
+#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
+		((unsigned char *)&f)[sizeof(float) - i - 1] =
+		    (unsigned char)(byte);
+#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
+	}
+
+	rtn_len = 64;
+	limit = 0;
+again:
+	if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
+		return (NULL);
+
+	if (snprintf(rtn, rtn_len, "%ff", f) >= (int)rtn_len) {
+		free(rtn);
+		if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
+			return (NULL);
+		rtn_len *= BUFFER_GROWFACTOR;
+		goto again;
+	}
+
+	return rtn;
+}
+
+static char *
+decode_fp_to_float128(const char *p, size_t len)
+{
+	long double f;
+	size_t rtn_len, limit, i;
+	int byte;
+	unsigned char buf[FLOAT_QUADRUPLE_BYTES];
+	char *rtn;
+
+	switch(sizeof(long double)) {
+	case FLOAT_QUADRUPLE_BYTES:
+		return (decode_fp_to_long_double(p, len));
+	case FLOAT_EXTENED_BYTES:
+		if (p == NULL || len == 0 || len % 2 != 0 ||
+		    len / 2 > FLOAT_QUADRUPLE_BYTES)
+			return (NULL);
+
+		memset(buf, 0, FLOAT_QUADRUPLE_BYTES);
+
+		for (i = 0; i < len / 2; ++i) {
+			byte = hex_to_dec(p[len - i * 2 - 1]) +
+			    hex_to_dec(p[len - i * 2 - 2]) * 16;
+			if (byte < 0 || byte > 255)
+				return (NULL);
+#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
+			buf[i] = (unsigned char)(byte);
+#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
+			buf[FLOAT_QUADRUPLE_BYTES - i -1] =
+			    (unsigned char)(byte);
+#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
+		}
+		memset(&f, 0, FLOAT_EXTENED_BYTES);
+
+#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
+		memcpy(&f, buf, FLOAT_EXTENED_BYTES);
+#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
+		memcpy(&f, buf + 6, FLOAT_EXTENED_BYTES);
+#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
+
+		rtn_len = 256;
+		limit = 0;
+again:
+		if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
+			return (NULL);
+
+		if (snprintf(rtn, rtn_len, "%Lfd", f) >= (int)rtn_len) {
+			free(rtn);
+			if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
+				return (NULL);
+			rtn_len *= BUFFER_GROWFACTOR;
+			goto again;
+		}
+
+		return (rtn);
+	default:
+		return (NULL);
+	}
+}
+
+static char *
+decode_fp_to_float80(const char *p, size_t len)
+{
+	long double f;
+	size_t rtn_len, limit, i;
+	int byte;
+	unsigned char buf[FLOAT_EXTENED_BYTES];
+	char *rtn;
+
+	switch(sizeof(long double)) {
+	case FLOAT_QUADRUPLE_BYTES:
+		if (p == NULL || len == 0 || len % 2 != 0 ||
+		    len / 2 > FLOAT_EXTENED_BYTES)
+			return (NULL);
+
+		memset(buf, 0, FLOAT_EXTENED_BYTES);
+
+		for (i = 0; i < len / 2; ++i) {
+			byte = hex_to_dec(p[len - i * 2 - 1]) +
+			    hex_to_dec(p[len - i * 2 - 2]) * 16;
+
+			if (byte < 0 || byte > 255)
+				return (NULL);
+
+#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
+			buf[i] = (unsigned char)(byte);
+#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
+			buf[FLOAT_EXTENED_BYTES - i -1] =
+			    (unsigned char)(byte);
+#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
+		}
+
+		memset(&f, 0, FLOAT_QUADRUPLE_BYTES);
+
+#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
+		memcpy(&f, buf, FLOAT_EXTENED_BYTES);
+#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
+		memcpy((unsigned char *)(&f) + 6, buf, FLOAT_EXTENED_BYTES);
+#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
+
+		rtn_len = 256;
+		limit = 0;
+again:
+		if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
+			return (NULL);
+
+		if (snprintf(rtn, rtn_len, "%Lfd", f) >= (int)rtn_len) {
+			free(rtn);
+			if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
+				return (NULL);
+			rtn_len *= BUFFER_GROWFACTOR;
+			goto again;
+		}
+
+		return (rtn);
+	case FLOAT_EXTENED_BYTES:
+		return (decode_fp_to_long_double(p, len));
+	default:
+		return (NULL);
+	}
+}
+
+static char *
+decode_fp_to_long_double(const char *p, size_t len)
+{
+	long double f;
+	size_t rtn_len, limit, i;
+	int byte;
+	char *rtn;
+
+	if (p == NULL || len == 0 || len % 2 != 0 ||
+	    len / 2 > sizeof(long double))
+		return (NULL);
+
+	memset(&f, 0, sizeof(long double));
+
+	for (i = 0; i < len / 2; ++i) {
+		byte = hex_to_dec(p[len - i * 2 - 1]) +
+		    hex_to_dec(p[len - i * 2 - 2]) * 16;
+
+		if (byte < 0 || byte > 255)
+			return (NULL);
+
+#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
+		((unsigned char *)&f)[i] = (unsigned char)(byte);
+#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
+		((unsigned char *)&f)[sizeof(long double) - i - 1] =
+		    (unsigned char)(byte);
+#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
+	}
+
+	rtn_len = 256;
+	limit = 0;
+again:
+	if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
+		return (NULL);
+
+	if (snprintf(rtn, rtn_len, "%Lfd", f) >= (int)rtn_len) {
+		free(rtn);
+		if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
+			return (NULL);
+		rtn_len *= BUFFER_GROWFACTOR;
+		goto again;
+	}
+
+	return (rtn);
+}
+
+/* Simple hex to integer function used by decode_to_* function. */
+static int
+hex_to_dec(char c)
+{
+
+	switch (c) {
+	case '0':
+		return (0);
+	case '1':
+		return (1);
+	case '2':
+		return (2);
+	case '3':
+		return (3);
+	case '4':
+		return (4);
+	case '5':
+		return (5);
+	case '6':
+		return (6);
+	case '7':
+		return (7);
+	case '8':
+		return (8);
+	case '9':
+		return (9);
+	case 'a':
+		return (10);
+	case 'b':
+		return (11);
+	case 'c':
+		return (12);
+	case 'd':
+		return (13);
+	case 'e':
+		return (14);
+	case 'f':
+		return (15);
+	default:
+		return (-1);
+	}
+}
+
+/**
+ * @brief Test input string is mangled by IA-64 C++ ABI style.
+ *
+ * Test string heads with "_Z" or "_GLOBAL__I_".
+ * @return Return 0 at false.
+ */
+bool
+is_cpp_mangled_gnu3(const char *org)
+{
+	size_t len;
+
+	len = strlen(org);
+	return ((len > 2 && *org == '_' && *(org + 1) == 'Z') ||
+	    (len > 11 && !strncmp(org, "_GLOBAL__I_", 11)));
+}
+
+static void
+vector_read_cmd_dest(struct vector_read_cmd *v)
+{
+
+	if (v == NULL)
+		return;
+
+	free(v->r_container);
+}
+
+static struct read_cmd_item *
+vector_read_cmd_find(struct vector_read_cmd *v, enum read_cmd dst)
+{
+	int i;
+
+	if (v == NULL || dst == READ_FAIL)
+		return (NULL);
+
+	for (i = (int) v->size - 1; i >= 0; i--)
+		if (v->r_container[i].cmd == dst)
+			return (&v->r_container[i]);
+
+	return (NULL);
+}
+
+static int
+vector_read_cmd_init(struct vector_read_cmd *v)
+{
+
+	if (v == NULL)
+		return (0);
+
+	v->size = 0;
+	v->capacity = VECTOR_DEF_CAPACITY;
+
+	if ((v->r_container = malloc(sizeof(*v->r_container) * v->capacity))
+	    == NULL)
+		return (0);
+
+	return (1);
+}
+
+static int
+vector_read_cmd_pop(struct vector_read_cmd *v)
+{
+
+	if (v == NULL || v->size == 0)
+		return (0);
+
+	--v->size;
+	v->r_container[v->size].cmd = READ_FAIL;
+	v->r_container[v->size].data = NULL;
+
+	return (1);
+}
+
+static int
+vector_read_cmd_push(struct vector_read_cmd *v, enum read_cmd cmd, void *data)
+{
+	struct read_cmd_item *tmp_r_ctn;
+	size_t tmp_cap;
+	size_t i;
+
+	if (v == NULL)
+		return (0);
+
+	if (v->size == v->capacity) {
+		tmp_cap = v->capacity * BUFFER_GROWFACTOR;
+		if ((tmp_r_ctn = malloc(sizeof(*tmp_r_ctn) * tmp_cap)) == NULL)
+			return (0);
+		for (i = 0; i < v->size; ++i)
+			tmp_r_ctn[i] = v->r_container[i];
+		free(v->r_container);
+		v->r_container = tmp_r_ctn;
+		v->capacity = tmp_cap;
+	}
+
+	v->r_container[v->size].cmd = cmd;
+	v->r_container[v->size].data = data;
+	++v->size;
+
+	return (1);
+}
+
+static void
+vector_type_qualifier_dest(struct vector_type_qualifier *v)
+{
+
+	if (v == NULL)
+		return;
+
+	free(v->q_container);
+	vector_str_dest(&v->ext_name);
+}
+
+/* size, capacity, ext_name */
+static int
+vector_type_qualifier_init(struct vector_type_qualifier *v)
+{
+
+	if (v == NULL)
+		return (0);
+
+	v->size = 0;
+	v->capacity = VECTOR_DEF_CAPACITY;
+
+	if ((v->q_container = malloc(sizeof(enum type_qualifier) * v->capacity))
+	    == NULL)
+		return (0);
+
+	assert(v->q_container != NULL);
+
+	if (vector_str_init(&v->ext_name) == false) {
+		free(v->q_container);
+		return (0);
+	}
+
+	return (1);
+}
+
+static int
+vector_type_qualifier_push(struct vector_type_qualifier *v,
+    enum type_qualifier t)
+{
+	enum type_qualifier *tmp_ctn;
+	size_t tmp_cap;
+	size_t i;
+
+	if (v == NULL)
+		return (0);
+
+	if (v->size == v->capacity) {
+		tmp_cap = v->capacity * BUFFER_GROWFACTOR;
+		if ((tmp_ctn = malloc(sizeof(enum type_qualifier) * tmp_cap))
+		    == NULL)
+			return (0);
+		for (i = 0; i < v->size; ++i)
+			tmp_ctn[i] = v->q_container[i];
+		free(v->q_container);
+		v->q_container = tmp_ctn;
+		v->capacity = tmp_cap;
+	}
+
+	v->q_container[v->size] = t;
+	++v->size;
+
+	return (1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/libelftc_hash.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,70 @@
+/*-
+ * Copyright (c) 2013, Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * An implementation of the Fowler-Noll-Vo hash function.
+ *
+ * References:
+ * - http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
+ * - http://www.isthe.com/chongo/tech/comp/fnv/
+ */
+
+#include <sys/types.h>
+
+#include <limits.h>
+
+#include "_libelftc.h"
+
+ELFTC_VCSID("$Id: libelftc_hash.c 2870 2013-01-07 10:38:43Z jkoshy $");
+
+/*
+ * Use the size of an 'int' to determine the magic numbers used by the
+ * hash function.
+ */
+
+#if	INT_MAX == 2147483647UL
+#define	FNV_PRIME		16777619UL
+#define FNV_OFFSET		2166136261UL
+#elif	INT_MAX == 18446744073709551615ULL
+#define	FNV_PRIME		1099511628211ULL
+#define	FNV_OFFSET		14695981039346656037ULL
+#else
+#error	sizeof(int) is unknown.
+#endif
+
+unsigned int
+libelftc_hash_string(const char *s)
+{
+	char c;
+	unsigned int hash;
+
+	for (hash = FNV_OFFSET; (c = *s) != '\0'; s++) {
+		hash ^= c;
+		hash *= FNV_PRIME;
+	}
+
+	return (hash);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/libelftc_vstr.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,359 @@
+/*-
+ * Copyright (c) 2008 Hyogeol Lee <hyogeollee@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <assert.h>
+#include <libelftc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "_libelftc.h"
+
+ELFTC_VCSID("$Id: libelftc_vstr.c 3531 2017-06-05 05:08:43Z kaiwang27 $");
+
+/**
+ * @file vector_str.c
+ * @brief Dynamic vector data for string implementation.
+ *
+ * Resemble to std::vector<std::string> in C++.
+ */
+
+static size_t	get_strlen_sum(const struct vector_str *v);
+static bool	vector_str_grow(struct vector_str *v);
+
+static size_t
+get_strlen_sum(const struct vector_str *v)
+{
+	size_t i, len = 0;
+
+	if (v == NULL)
+		return (0);
+
+	assert(v->size > 0);
+
+	for (i = 0; i < v->size; ++i)
+		len += strlen(v->container[i]);
+
+	return (len);
+}
+
+/**
+ * @brief Deallocate resource in vector_str.
+ */
+void
+vector_str_dest(struct vector_str *v)
+{
+	size_t i;
+
+	if (v == NULL)
+		return;
+
+	for (i = 0; i < v->size; ++i)
+		free(v->container[i]);
+
+	free(v->container);
+}
+
+/**
+ * @brief Find string in vector_str.
+ * @param v Destination vector.
+ * @param o String to find.
+ * @param l Length of the string.
+ * @return -1 at failed, 0 at not found, 1 at found.
+ */
+int
+vector_str_find(const struct vector_str *v, const char *o, size_t l)
+{
+	size_t i;
+
+	if (v == NULL || o == NULL)
+		return (-1);
+
+	for (i = 0; i < v->size; ++i)
+		if (strncmp(v->container[i], o, l) == 0)
+			return (1);
+
+	return (0);
+}
+
+/**
+ * @brief Get new allocated flat string from vector.
+ *
+ * If l is not NULL, return length of the string.
+ * @param v Destination vector.
+ * @param l Length of the string.
+ * @return NULL at failed or NUL terminated new allocated string.
+ */
+char *
+vector_str_get_flat(const struct vector_str *v, size_t *l)
+{
+	ssize_t elem_pos, elem_size, rtn_size;
+	size_t i;
+	char *rtn;
+
+	if (v == NULL || v->size == 0)
+		return (NULL);
+
+	if ((rtn_size = get_strlen_sum(v)) == 0)
+		return (NULL);
+
+	if ((rtn = malloc(sizeof(char) * (rtn_size + 1))) == NULL)
+		return (NULL);
+
+	elem_pos = 0;
+	for (i = 0; i < v->size; ++i) {
+		elem_size = strlen(v->container[i]);
+
+		memcpy(rtn + elem_pos, v->container[i], elem_size);
+
+		elem_pos += elem_size;
+	}
+
+	rtn[rtn_size] = '\0';
+
+	if (l != NULL)
+		*l = rtn_size;
+
+	return (rtn);
+}
+
+static bool
+vector_str_grow(struct vector_str *v)
+{
+	size_t i, tmp_cap;
+	char **tmp_ctn;
+
+	if (v == NULL)
+		return (false);
+
+	assert(v->capacity > 0);
+
+	tmp_cap = v->capacity * BUFFER_GROWFACTOR;
+
+	assert(tmp_cap > v->capacity);
+
+	if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL)
+		return (false);
+
+	for (i = 0; i < v->size; ++i)
+		tmp_ctn[i] = v->container[i];
+
+	free(v->container);
+
+	v->container = tmp_ctn;
+	v->capacity = tmp_cap;
+
+	return (true);
+}
+
+/**
+ * @brief Initialize vector_str.
+ * @return false at failed, true at success.
+ */
+bool
+vector_str_init(struct vector_str *v)
+{
+
+	if (v == NULL)
+		return (false);
+
+	v->size = 0;
+	v->capacity = VECTOR_DEF_CAPACITY;
+
+	assert(v->capacity > 0);
+
+	if ((v->container = malloc(sizeof(char *) * v->capacity)) == NULL)
+		return (false);
+
+	assert(v->container != NULL);
+
+	return (true);
+}
+
+/**
+ * @brief Remove last element in vector_str.
+ * @return false at failed, true at success.
+ */
+bool
+vector_str_pop(struct vector_str *v)
+{
+
+	if (v == NULL)
+		return (false);
+
+	if (v->size == 0)
+		return (true);
+
+	--v->size;
+
+	free(v->container[v->size]);
+	v->container[v->size] = NULL;
+
+	return (true);
+}
+
+/**
+ * @brief Push back string to vector.
+ * @return false at failed, true at success.
+ */
+bool
+vector_str_push(struct vector_str *v, const char *str, size_t len)
+{
+
+	if (v == NULL || str == NULL)
+		return (false);
+
+	if (v->size == v->capacity && vector_str_grow(v) == false)
+		return (false);
+
+	if ((v->container[v->size] = malloc(sizeof(char) * (len + 1))) == NULL)
+		return (false);
+
+	snprintf(v->container[v->size], len + 1, "%s", str);
+
+	++v->size;
+
+	return (true);
+}
+
+/**
+ * @brief Push front org vector to det vector.
+ * @return false at failed, true at success.
+ */
+bool
+vector_str_push_vector_head(struct vector_str *dst, struct vector_str *org)
+{
+	size_t i, j, tmp_cap;
+	char **tmp_ctn;
+
+	if (dst == NULL || org == NULL)
+		return (false);
+
+	tmp_cap = (dst->size + org->size) * BUFFER_GROWFACTOR;
+
+	if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL)
+		return (false);
+
+	for (i = 0; i < org->size; ++i)
+		if ((tmp_ctn[i] = strdup(org->container[i])) == NULL) {
+			for (j = 0; j < i; ++j)
+				free(tmp_ctn[j]);
+
+			free(tmp_ctn);
+
+			return (false);
+		}
+
+	for (i = 0; i < dst->size; ++i)
+		tmp_ctn[i + org->size] = dst->container[i];
+
+	free(dst->container);
+
+	dst->container = tmp_ctn;
+	dst->capacity = tmp_cap;
+	dst->size += org->size;
+
+	return (true);
+}
+
+/**
+ * @brief Push org vector to the tail of det vector.
+ * @return false at failed, true at success.
+ */
+bool
+vector_str_push_vector(struct vector_str *dst, struct vector_str *org)
+{
+	size_t i, j, tmp_cap;
+	char **tmp_ctn;
+
+	if (dst == NULL || org == NULL)
+		return (false);
+
+	tmp_cap = (dst->size + org->size) * BUFFER_GROWFACTOR;
+
+	if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL)
+		return (false);
+
+	for (i = 0; i < dst->size; ++i)
+		tmp_ctn[i] = dst->container[i];
+
+	for (i = 0; i < org->size; ++i)
+		if ((tmp_ctn[i + dst->size] = strdup(org->container[i])) ==
+		    NULL) {
+			for (j = 0; j < i + dst->size; ++j)
+				free(tmp_ctn[j]);
+
+			free(tmp_ctn);
+
+			return (false);
+		}
+
+	free(dst->container);
+
+	dst->container = tmp_ctn;
+	dst->capacity = tmp_cap;
+	dst->size += org->size;
+
+	return (true);
+}
+
+/**
+ * @brief Get new allocated flat string from vector between begin and end.
+ *
+ * If r_len is not NULL, string length will be returned.
+ * @return NULL at failed or NUL terminated new allocated string.
+ */
+char *
+vector_str_substr(const struct vector_str *v, size_t begin, size_t end,
+    size_t *r_len)
+{
+	size_t cur, i, len;
+	char *rtn;
+
+	if (v == NULL || begin > end)
+		return (NULL);
+
+	len = 0;
+	for (i = begin; i < end + 1; ++i)
+		len += strlen(v->container[i]);
+
+	if ((rtn = malloc(sizeof(char) * (len + 1))) == NULL)
+		return (NULL);
+
+	if (r_len != NULL)
+		*r_len = len;
+
+	cur = 0;
+	for (i = begin; i < end + 1; ++i) {
+		len = strlen(v->container[i]);
+		memcpy(rtn + cur, v->container[i], len);
+		cur += len;
+	}
+	rtn[cur] = '\0';
+
+	return (rtn);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/make-toolchain-version	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,110 @@
+#!/bin/sh
+#
+# This script generates a project-wide version identifier for use by
+# the `elftc_version()' API.
+#
+# $Id: make-toolchain-version 3414 2016-02-16 22:55:28Z jkoshy $
+
+#
+# Defaults.
+#
+buildhost=`uname -s`
+elftcname="elftoolchain"
+options="e:h:o:r:t:"
+top=""
+version="HEAD"
+versionfile="elftc_version.c"
+progname=`basename ${0}`
+
+usage()
+{
+    exec >&2
+
+    # Print a message, if supplied.
+    if [ -n "${*}" ]; then echo "##${@}"; fi
+
+    echo "Usage: ${progname} [options]"
+    echo "	Generate a toolchain-wide version number"
+    echo "	-e PROJECTNAME Set the project name [default: ${elftcname}]."
+    echo "	-h HOSTOS      Set the build OS [default: ${buildhost}]."
+    echo "	-o OUTPUT      Set the output file [default: ${versionfile}]."
+    echo "	-r VERSION     Set the version string [default: ${version}]."
+    echo "	-t TOPDIR      Set the top-of-tree directory [required]."
+    exit 1
+}
+
+#
+# Parse options.
+#
+
+while getopts ${options} option
+do
+    case ${option} in
+	'e') elftcname="${OPTARG}"   ;;
+	'h') buildhost="${OPTARG}"   ;;
+	'o') versionfile="${OPTARG}" ;;
+	'r') version="${OPTARG}"      ;;
+	't') top="${OPTARG}"         ;;
+	'?') usage                   ;;
+    esac
+done
+
+[ -n "${top}" ] || usage
+
+# Try to determine the in-tree revision number.
+#
+# This script attempts to handle the case where our sources have been
+# incorporated into an operating system's base sources.
+#
+# - If SVN is detected, we use the `svninfo' tool to determine the
+#   in-tree revision number.
+# - If CVS is detected, we use the string `unknown'.
+# - Otherwise, we use `git --describe'.
+
+curdir=`pwd`
+cd ${top} || usage "ERROR: Cannot change directory to \"${top}\"."
+
+if [ -d CVS ]; then		# Look for CVS (NetBSD).
+    versionstring=" cvs:unknown"
+else				# Try git (DragonFlyBSD).
+    gitversion="$(git describe --all --dirty --long 2> /dev/null)"
+    if [ -n "${gitversion}" ]; then
+        versionstring=" git:${gitversion}"
+    else   # Assume an SVN checkout (SourceForge or FreeBSD).
+        svnversion="$(svnversion)"
+        if [ -n "${svnversion}" ]; then
+	    versionstring=" svn:$(svnversion)"
+        fi
+    fi
+fi
+
+if [ -z "${versionstring}" ]; then
+    echo "ERROR: cannot determine a revision number." 1>&2
+    exit 1
+fi
+
+cd ${curdir} || usage "Cannot change back to ${curdir}."
+
+#
+# Only replace the source file if its content has changed.
+#
+tmpfile=`mktemp ${TMPDIR:-/tmp}/MV.XXXXXXX`
+trap "rm -f ${tmpfile};" 0 1 2 3 15
+
+cat > ${tmpfile} <<EOF
+/* WARNING: Generated by "${progname}". */
+
+#include <sys/types.h>
+#include <libelftc.h>
+
+const char *
+elftc_version(void)
+{
+	return "${elftcname} ${version} ${buildhost}${versionstring}";
+}
+EOF
+
+if ! cmp -s ${tmpfile} ${versionfile}; then
+    echo "@ ${progname}: building \"${versionfile}\"."
+    cp ${tmpfile} ${versionfile} || exit ${?}
+fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/os.FreeBSD.mk	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,7 @@
+#
+# Building for a FreeBSD target.
+#
+# $Id: os.freebsd.mk 189 2008-07-20 10:38:08Z jkoshy $
+
+# Symbol versioning support [FreeBSD 7.X and later]
+VERSION_MAP=		${.CURDIR}/Version.map
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/os.Linux.mk	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,3 @@
+# $Id: os.Linux.mk 3210 2015-05-17 13:40:49Z kaiwang27 $
+
+CFLAGS+=	-Wall -D_GNU_SOURCE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libelftc/os.NetBSD.mk	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,2 @@
+# TODO(#511): Revert after the source tree is -Wconversion clean.
+WARNS=5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libpe/Makefile	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,32 @@
+# $Id: Makefile 3594 2018-04-11 18:26:50Z jkoshy $
+
+TOP=	..
+
+LIB=	pe
+
+SRCS=	libpe_buffer.c	\
+	libpe_coff.c	\
+	libpe_dos.c	\
+	libpe_init.c	\
+	libpe_rich.c	\
+	libpe_section.c	\
+	libpe_utils.c	\
+	pe_buffer.c	\
+	pe_cntl.c	\
+	pe_coff.c	\
+	pe_dos.c	\
+	pe_flag.c	\
+	pe_init.c	\
+	pe_rich.c	\
+	pe_section.c	\
+	pe_symtab.c	\
+	pe_update.c
+
+INCS=		libpe.h pe.h
+INCSDIR=	/usr/include
+
+SHLIB_MAJOR=	1
+
+WARNS?=	6
+
+.include "${TOP}/mk/elftoolchain.lib.mk"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libpe/_libpe.h	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,213 @@
+/*-
+ * Copyright (c) 2015 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: _libpe.h 3312 2016-01-10 09:23:51Z kaiwang27 $
+ */
+
+#ifndef	__LIBPE_H_
+#define	__LIBPE_H_
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include "libpe.h"
+
+#include "_elftc.h"
+
+typedef struct _PE_SecBuf {
+	PE_Buffer	 sb_pb;		/* application buffer */
+	PE_Scn		*sb_ps;		/* PE_Scn pointer */
+	unsigned int	 sb_flags;	/* buffer flags */
+	STAILQ_ENTRY(_PE_SecBuf) sb_next;
+} PE_SecBuf;
+
+struct _PE_Scn {
+	PE		*ps_pe;		/* PE descriptor */
+	PE_SecHdr	 ps_sh;		/* section header */
+	unsigned int	 ps_ndx;	/* 1-based section index */
+	unsigned int	 ps_flags;	/* section flags */
+	unsigned int	 ps_falign;	/* section file alignment */
+	STAILQ_HEAD(, _PE_SecBuf) ps_b; /* buffer list */
+	STAILQ_ENTRY(_PE_Scn) ps_next;
+};
+
+struct _PE {
+	int		 pe_fd;		/* file descriptor */
+	PE_Cmd		 pe_cmd;	/* open mode */
+	PE_Object	 pe_obj;	/* PE32/PE32+/COFF */
+	size_t		 pe_fsize;	/* file size */
+	unsigned int	 pe_flags;	/* library flags */
+	PE_DosHdr	*pe_dh;		/* MS-DOS header */
+	char		*pe_stub;	/* MS-DOS stub */
+	size_t		 pe_stub_ex;	/* MS-DOS stub len (exclude hdr) */
+	char		*pe_stub_app;	/* MS-DOS stub (app supplied) */
+	size_t		 pe_stub_app_sz; /* MS-DOS stub len (app supplied) */
+	PE_RichHdr	*pe_rh;		/* rich header */
+	char		*pe_rh_start;	/* pointer to rich header */
+	PE_CoffHdr	*pe_ch;		/* COFF header */
+	PE_OptHdr	*pe_oh;		/* optional header */
+	PE_DataDir	*pe_dd;		/* data directories */
+	unsigned int	 pe_nscn;	/* num. of sections */
+	char		*pe_symtab;	/* COFF symbol table */
+	size_t		 pe_symbtab_sz; /* size of symbol table */
+	unsigned int	 pe_nsym;	/* num. of symbols */
+	unsigned int	 pe_rvamax;	/* maximum RVA */
+	STAILQ_HEAD(, _PE_Scn) pe_scn;	/* section list */
+};
+
+/* Library internal flags  */
+#define	LIBPE_F_API_MASK		0x000FFFU
+#define	LIBPE_F_SPECIAL_FILE		0x001000U
+#define	LIBPE_F_BAD_DOS_HEADER		0x002000U
+#define	LIBPE_F_BAD_PE_HEADER		0x004000U
+#define	LIBPE_F_BAD_COFF_HEADER		0x008000U
+#define	LIBPE_F_BAD_OPT_HEADER		0x010000U
+#define	LIBPE_F_BAD_SEC_HEADER		0x020000U
+#define	LIBPE_F_LOAD_DOS_STUB		0x040000U
+#define	LIBPE_F_FD_DONE			0x080000U
+#define	LIBPE_F_DIRTY_DOS_HEADER	0x100000U
+#define	LIBPE_F_DIRTY_COFF_HEADER	0x200000U
+#define	LIBPE_F_DIRTY_OPT_HEADER	0x400000U
+#define	LIBPE_F_DIRTY_SEC_HEADER	0x800000U
+
+/* Internal section flags */
+#define	LIBPE_F_LOAD_SECTION		0x1000U
+#define	LIBPE_F_STRIP_SECTION		0x2000U
+
+/* Internal buffer flags */
+#define	LIBPE_F_BUFFER_MALLOCED		0x1000U
+
+/* Library internal defines */
+#define	PE_DOS_MAGIC		0x5a4dU
+#define	PE_RICH_TEXT		"Rich"
+#define	PE_RICH_HIDDEN		0x536e6144U /* DanS */
+#define	PE_SIGNATURE		0x4550U	   /* PE\0\0 */
+#define	PE_COFF_OPT_SIZE_32	224
+#define	PE_COFF_OPT_SIZE_32P	240
+#define	PE_SYM_ENTRY_SIZE	18
+
+/* Encode/Decode macros */
+#if defined(ELFTC_NEED_BYTEORDER_EXTENSIONS)
+static  __inline uint16_t
+le16dec(const void *pp)
+{
+	unsigned char const *p = (unsigned char const *)pp;
+
+	return ((p[1] << 8) | p[0]);
+}
+
+static __inline uint32_t
+le32dec(const void *pp)
+{
+	unsigned char const *p = (unsigned char const *)pp;
+
+	return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]);
+}
+
+static __inline uint64_t
+le64dec(const void *pp)
+{
+	unsigned char const *p = (unsigned char const *)pp;
+
+	return (((uint64_t)le32dec(p + 4) << 32) | le32dec(p));
+}
+
+static __inline void
+le16enc(void *pp, uint16_t u)
+{
+	unsigned char *p = (unsigned char *)pp;
+
+	p[0] = u & 0xff;
+	p[1] = (u >> 8) & 0xff;
+}
+
+static __inline void
+le32enc(void *pp, uint32_t u)
+{
+	unsigned char *p = (unsigned char *)pp;
+
+	p[0] = u & 0xff;
+	p[1] = (u >> 8) & 0xff;
+	p[2] = (u >> 16) & 0xff;
+	p[3] = (u >> 24) & 0xff;
+}
+
+static __inline void
+le64enc(void *pp, uint64_t u)
+{
+	unsigned char *p = (unsigned char *)pp;
+
+	le32enc(p, (uint32_t)(u & 0xffffffffU));
+	le32enc(p + 4, (uint32_t)(u >> 32));
+}
+#endif	/* ELFTC_NEED_BYTEORDER_EXTENSIONS */
+
+#define	PE_READ16(p,v)	do {			\
+	(v) = le16dec((p));			\
+	(p) += 2;				\
+} while(0)
+
+#define	PE_READ32(p,v)	do {			\
+	(v) = le32dec((p));			\
+	(p) += 4;				\
+} while(0)
+
+#define	PE_WRITE16(p,v) do {			\
+	le16enc((p), (v));			\
+	(p) += 2;				\
+} while(0)
+
+#define	PE_WRITE32(p,v) do {			\
+	le32enc((p), (v));			\
+	(p) += 4;				\
+} while(0)
+
+
+/* Internal function declarations */
+off_t		libpe_align(PE *, off_t, size_t);
+PE_SecBuf	*libpe_alloc_buffer(PE_Scn *, size_t);
+PE_Scn		*libpe_alloc_scn(PE *);
+int		libpe_load_all_sections(PE *);
+int		libpe_load_section(PE *, PE_Scn *);
+int		libpe_open_object(PE *);
+int		libpe_pad(PE *, size_t);
+int		libpe_parse_msdos_header(PE *, char *);
+int		libpe_parse_coff_header(PE *, char *);
+int		libpe_parse_rich_header(PE *);
+int		libpe_parse_section_headers(PE *);
+int		libpe_read_msdos_stub(PE *);
+void		libpe_release_buffer(PE_SecBuf *);
+void		libpe_release_object(PE *);
+void		libpe_release_scn(PE_Scn *);
+size_t		libpe_resync_buffers(PE_Scn *);
+int		libpe_resync_sections(PE *, off_t);
+int		libpe_write_buffers(PE_Scn *);
+off_t		libpe_write_coff_header(PE *, off_t);
+off_t		libpe_write_msdos_stub(PE *, off_t);
+off_t		libpe_write_pe_header(PE *, off_t);
+off_t		libpe_write_sections(PE *, off_t);
+off_t		libpe_write_section_headers(PE *, off_t);
+
+#endif	/* !__LIBPE_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libpe/libpe.h	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,121 @@
+/*-
+ * Copyright (c) 2015 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: libpe.h 3312 2016-01-10 09:23:51Z kaiwang27 $
+ */
+
+#ifndef	_LIBPE_H_
+#define	_LIBPE_H_
+
+#include <sys/types.h>
+
+#include "pe.h"
+
+/* Library private data structures */
+typedef struct _PE PE;
+typedef struct _PE_Scn PE_Scn;
+
+/* Section buffers */
+typedef struct PE_Buffer {
+        unsigned int	 pb_align;
+	off_t		 pb_off;
+	size_t		 pb_size;
+	void		*pb_buf;
+} PE_Buffer;
+
+/* Object types */
+typedef enum {
+	PE_O_UNKNOWN = 0,
+	PE_O_PE32,
+	PE_O_PE32P,
+	PE_O_COFF,
+} PE_Object;
+
+/* Commands */
+typedef enum {
+	PE_C_NULL = 0,
+	PE_C_CLR,
+	PE_C_FDDONE,
+	PE_C_FDREAD,
+	PE_C_RDWR,
+	PE_C_READ,
+	PE_C_SET,
+	PE_C_WRITE,
+	PE_C_NUM
+} PE_Cmd;
+
+/* Flags defined by the API. */
+#define	PE_F_DIRTY		0x001U
+#define	PE_F_STRIP_DOS_STUB	0x002U
+#define	PE_F_STRIP_RICH_HEADER	0x004U
+#define	PE_F_STRIP_SYMTAB	0x008U
+#define	PE_F_STRIP_DEBUG	0x010U
+#define	PE_F_STRIP_SECTION	0x020U
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PE_CoffHdr	*pe_coff_header(PE *);
+int		pe_cntl(PE *, PE_Cmd);
+PE_DataDir	*pe_data_dir(PE *);
+void		pe_finish(PE *);
+int		pe_flag(PE *, PE_Cmd, unsigned int);
+int		pe_flag_buffer(PE_Buffer *, PE_Cmd, unsigned int);
+int		pe_flag_coff_header(PE *, PE_Cmd, unsigned int);
+int		pe_flag_data_dir(PE *, PE_Cmd, unsigned int);
+int		pe_flag_dos_header(PE *, PE_Cmd, unsigned int);
+int		pe_flag_opt_header(PE *, PE_Cmd, unsigned int);
+int		pe_flag_section_header(PE_Scn *, PE_Cmd, unsigned int);
+int		pe_flag_scn(PE_Scn *, PE_Cmd, unsigned int);
+PE_Buffer	*pe_getbuffer(PE_Scn *, PE_Buffer *);
+PE_Scn 		*pe_getscn(PE *, size_t);
+PE		*pe_init(int, PE_Cmd, PE_Object);
+PE_Scn		*pe_insertscn(PE *, size_t);
+PE_DosHdr	*pe_msdos_header(PE *);
+char		*pe_msdos_stub(PE *, size_t *);
+size_t		pe_ndxscn(PE_Scn *);
+PE_Buffer	*pe_newbuffer(PE_Scn *);
+PE_Scn		*pe_newscn(PE *);
+PE_Scn		*pe_nextscn(PE *, PE_Scn *);
+PE_Object	pe_object(PE *);
+PE_OptHdr	*pe_opt_header(PE *);
+PE_RichHdr	*pe_rich_header(PE *);
+int		pe_rich_header_validate(PE *);
+PE_SecHdr	*pe_section_header(PE_Scn *);
+off_t		pe_update(PE *);
+int		pe_update_coff_header(PE *, PE_CoffHdr *);
+int		pe_update_opt_header(PE *, PE_OptHdr *);
+int		pe_update_data_dir(PE *, PE_DataDir *);
+int		ps_update_msdos_header(PE *, PE_DosHdr *);
+int		ps_update_msdos_stub(PE *, char *, size_t);
+int		pe_update_section_header(PE_Scn *, PE_SecHdr *);
+int		pe_update_symtab(PE *, char *, size_t, unsigned int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* !_LIBPE_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libpe/libpe_buffer.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,185 @@
+/*-
+ * Copyright (c) 2016 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: libpe_buffer.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+PE_SecBuf *
+libpe_alloc_buffer(PE_Scn *ps, size_t sz)
+{
+	PE_SecBuf *sb;
+
+	if ((sb = malloc(sizeof(PE_SecBuf))) == NULL) {
+		errno = ENOMEM;
+		return (NULL);
+	}
+
+	sb->sb_ps = ps;
+	sb->sb_flags = 0;
+	sb->sb_pb.pb_align = 1;
+	sb->sb_pb.pb_off = 0;
+	sb->sb_pb.pb_size = sz;
+	if (sz > 0) {
+		if ((sb->sb_pb.pb_buf = malloc(sz)) == NULL) {
+			free(sb);
+			errno = ENOMEM;
+			return (NULL);
+		}
+		sb->sb_flags |= LIBPE_F_BUFFER_MALLOCED;
+	} else
+		sb->sb_pb.pb_buf = NULL;
+
+	STAILQ_INSERT_TAIL(&ps->ps_b, sb, sb_next);
+
+	return (sb);
+}
+
+void
+libpe_release_buffer(PE_SecBuf *sb)
+{
+	PE_Scn *ps;
+
+	assert(sb != NULL);
+
+	ps = sb->sb_ps;
+
+	STAILQ_REMOVE(&ps->ps_b, sb, _PE_SecBuf, sb_next);
+
+	if (sb->sb_flags & LIBPE_F_BUFFER_MALLOCED)
+		free(sb->sb_pb.pb_buf);
+
+	free(sb);
+}
+
+static int
+cmp_sb(PE_SecBuf *a, PE_SecBuf *b)
+{
+
+	if (a->sb_pb.pb_off < b->sb_pb.pb_off)
+		return (-1);
+	else if (a->sb_pb.pb_off == b->sb_pb.pb_off)
+		return (0);
+	else
+		return (1);
+}
+
+static void
+sort_buffers(PE_Scn *ps)
+{
+
+	if (STAILQ_EMPTY(&ps->ps_b))
+		return;
+
+	STAILQ_SORT(&ps->ps_b, _PE_SecBuf, sb_next, cmp_sb);
+}
+
+size_t
+libpe_resync_buffers(PE_Scn *ps)
+{
+	PE_SecBuf *sb;
+	PE_Buffer *pb;
+	size_t sz;
+
+	assert(ps->ps_flags & LIBPE_F_LOAD_SECTION);
+
+	sort_buffers(ps);
+
+	sz = 0;
+	STAILQ_FOREACH(sb, &ps->ps_b, sb_next) {
+		if (ps->ps_flags & PE_F_DIRTY)
+			sb->sb_flags |= PE_F_DIRTY;
+
+		pb = (PE_Buffer *) sb;
+		if (pb->pb_align > ps->ps_falign)
+			pb->pb_align = ps->ps_falign;
+		if (pb->pb_buf == NULL || pb->pb_size == 0)
+			continue;
+
+		sz = roundup(sz, pb->pb_align);
+
+		if (pb->pb_off != (off_t) sz) {
+			pb->pb_off = sz;
+			sb->sb_flags |= PE_F_DIRTY;
+		}
+		sz += pb->pb_size;
+	}
+
+	return (sz);
+}
+
+int
+libpe_write_buffers(PE_Scn *ps)
+{
+	PE *pe;
+	PE_SecBuf *sb;
+	PE_Buffer *pb;
+	off_t off;
+
+	assert(ps->ps_flags & LIBPE_F_LOAD_SECTION);
+
+	pe = ps->ps_pe;
+
+	off = 0;
+	STAILQ_FOREACH(sb, &ps->ps_b, sb_next) {
+		pb = &sb->sb_pb;
+		if (pb->pb_buf == NULL || pb->pb_size == 0)
+			continue;
+
+		if ((sb->sb_flags & PE_F_DIRTY) == 0) {
+			assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0);
+			if (lseek(pe->pe_fd, (off_t) pb->pb_size, SEEK_CUR) <
+			    0) {
+				errno = EIO;
+				return (-1);
+			}
+			goto next_buf;
+		}
+
+		if (pb->pb_off > off) {
+			if (libpe_pad(pe, pb->pb_off - off) < 0)
+				return (-1);
+			off = pb->pb_off;
+		}
+
+		if (write(pe->pe_fd, pb->pb_buf, pb->pb_size) !=
+		    (ssize_t) pb->pb_size) {
+			errno = EIO;
+			return (-1);
+		}
+
+	next_buf:
+		off += pb->pb_size;
+	}
+
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libpe/libpe_coff.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,535 @@
+/*-
+ * Copyright (c) 2015 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: libpe_coff.c 3326 2016-01-16 17:46:17Z kaiwang27 $");
+
+int
+libpe_parse_coff_header(PE *pe, char *hdr)
+{
+	char tmp[128];
+	PE_CoffHdr *ch;
+	PE_OptHdr *oh;
+	PE_DataDir *dd;
+	unsigned p, r, s;
+	int i;
+
+	if ((ch = malloc(sizeof(PE_CoffHdr))) == NULL) {
+		errno = ENOMEM;
+		return (-1);
+	}
+
+	PE_READ16(hdr, ch->ch_machine);
+	PE_READ16(hdr, ch->ch_nsec);
+	PE_READ32(hdr, ch->ch_timestamp);
+	PE_READ32(hdr, ch->ch_symptr);
+	PE_READ32(hdr, ch->ch_nsym);
+	PE_READ16(hdr, ch->ch_optsize);
+	PE_READ16(hdr, ch->ch_char);
+
+	pe->pe_ch = ch;
+
+	/*
+	 * The Optional header is omitted for object files.
+	 */
+	if (ch->ch_optsize == 0)
+		return (libpe_parse_section_headers(pe));
+
+	if ((oh = calloc(1, sizeof(PE_OptHdr))) == NULL) {
+		errno = ENOMEM;
+		return (-1);
+	}
+	pe->pe_oh = oh;
+
+#define READ_OPT(n)							\
+	do {								\
+		/*							\
+		 * Since the Optional Header size is variable, we must	\
+		 * check if the requested read size will overrun the	\
+		 * remaining header bytes.				\
+		 */							\
+		if (p + (n) > ch->ch_optsize) {				\
+			/* Consume the "extra" bytes */			\
+			r = ch->ch_optsize - p;				\
+			if (read(pe->pe_fd, tmp, r) != (ssize_t) r) {	\
+				pe->pe_flags |= LIBPE_F_BAD_SEC_HEADER;\
+				return (0);				\
+			}						\
+			return (libpe_parse_section_headers(pe));	\
+		}							\
+		if (read(pe->pe_fd, tmp, (n)) != (ssize_t) (n)) {	\
+			pe->pe_flags |= LIBPE_F_BAD_OPT_HEADER;	\
+			return (0);					\
+		}							\
+		p += (n);						\
+	} while (0)
+#define	READ_OPT8(v) do { READ_OPT(1); (v) = *tmp; } while(0)
+#define	READ_OPT16(v) do { READ_OPT(2); (v) = le16dec(tmp); } while(0)
+#define	READ_OPT32(v) do { READ_OPT(4); (v) = le32dec(tmp); } while(0)
+#define	READ_OPT64(v) do { READ_OPT(8); (v) = le64dec(tmp); } while(0)
+
+	/*
+	 * Read in the Optional header. Size of some fields are depending
+	 * on the PE format specified by the oh_magic field. (PE32 or PE32+)
+	 */
+
+	p = 0;
+	READ_OPT16(oh->oh_magic);
+	if (oh->oh_magic == PE_FORMAT_32P)
+		pe->pe_obj = PE_O_PE32P;
+	READ_OPT8(oh->oh_ldvermajor);
+	READ_OPT8(oh->oh_ldverminor);
+	READ_OPT32(oh->oh_textsize);
+	READ_OPT32(oh->oh_datasize);
+	READ_OPT32(oh->oh_bsssize);
+	READ_OPT32(oh->oh_entry);
+	READ_OPT32(oh->oh_textbase);
+	if (oh->oh_magic != PE_FORMAT_32P) {
+		READ_OPT32(oh->oh_database);
+		READ_OPT32(oh->oh_imgbase);
+	} else
+		READ_OPT64(oh->oh_imgbase);
+	READ_OPT32(oh->oh_secalign);
+	READ_OPT32(oh->oh_filealign);
+	READ_OPT16(oh->oh_osvermajor);
+	READ_OPT16(oh->oh_osverminor);
+	READ_OPT16(oh->oh_imgvermajor);
+	READ_OPT16(oh->oh_imgverminor);
+	READ_OPT16(oh->oh_subvermajor);
+	READ_OPT16(oh->oh_subverminor);
+	READ_OPT32(oh->oh_win32ver);
+	READ_OPT32(oh->oh_imgsize);
+	READ_OPT32(oh->oh_hdrsize);
+	READ_OPT32(oh->oh_checksum);
+	READ_OPT16(oh->oh_subsystem);
+	READ_OPT16(oh->oh_dllchar);
+	if (oh->oh_magic != PE_FORMAT_32P) {
+		READ_OPT32(oh->oh_stacksizer);
+		READ_OPT32(oh->oh_stacksizec);
+		READ_OPT32(oh->oh_heapsizer);
+		READ_OPT32(oh->oh_heapsizec);
+	} else {
+		READ_OPT64(oh->oh_stacksizer);
+		READ_OPT64(oh->oh_stacksizec);
+		READ_OPT64(oh->oh_heapsizer);
+		READ_OPT64(oh->oh_heapsizec);
+	}
+	READ_OPT32(oh->oh_ldrflags);
+	READ_OPT32(oh->oh_ndatadir);
+
+	/*
+	 * Read in the Data Directories.
+	 */
+
+	if (oh->oh_ndatadir > 0) {
+		if ((dd = calloc(1, sizeof(PE_DataDir))) == NULL) {
+			errno = ENOMEM;
+			return (-1);
+		}
+		pe->pe_dd = dd;
+
+		dd->dd_total = oh->oh_ndatadir < PE_DD_MAX ? oh->oh_ndatadir :
+			PE_DD_MAX;
+
+		for (i = 0; (uint32_t) i < dd->dd_total; i++) {
+			READ_OPT32(dd->dd_e[i].de_addr);
+			READ_OPT32(dd->dd_e[i].de_size);
+		}
+	}
+
+	/* Consume the remaining bytes in the Optional header, if any. */
+	if (ch->ch_optsize > p) {
+		r = ch->ch_optsize - p;
+		for (; r > 0; r -= s) {
+			s = r > sizeof(tmp) ? sizeof(tmp) : r;
+			if (read(pe->pe_fd, tmp, s) != (ssize_t) s) {
+				pe->pe_flags |= LIBPE_F_BAD_SEC_HEADER;
+				return (0);
+			}
+		}
+	}
+
+	return (libpe_parse_section_headers(pe));
+}
+
+off_t
+libpe_write_pe_header(PE *pe, off_t off)
+{
+	char tmp[4];
+
+	if (pe->pe_cmd == PE_C_RDWR &&
+	    (pe->pe_flags & LIBPE_F_BAD_PE_HEADER) == 0) {
+		assert(pe->pe_dh != NULL);
+		off = lseek(pe->pe_fd, (off_t) pe->pe_dh->dh_lfanew + 4,
+		    SEEK_SET);
+		return (off);
+	}
+
+	/*
+	 * PE Header should to be aligned on 8-byte boundary according to
+	 * the PE/COFF specification.
+	 */
+	if ((off = libpe_align(pe, off, 8)) < 0)
+		return (-1);
+
+	le32enc(tmp, PE_SIGNATURE);
+	if (write(pe->pe_fd, tmp, sizeof(tmp)) != (ssize_t) sizeof(tmp)) {
+		errno = EIO;
+		return (-1);
+	}
+
+	off += 4;
+
+	pe->pe_flags &= ~LIBPE_F_BAD_PE_HEADER;
+
+	/* Trigger rewrite for the following headers. */
+	pe->pe_flags |= LIBPE_F_DIRTY_COFF_HEADER;
+	pe->pe_flags |= LIBPE_F_DIRTY_OPT_HEADER;
+
+	return (off);
+}
+
+off_t
+libpe_write_coff_header(PE *pe, off_t off)
+{
+	char tmp[128], *hdr;
+	PE_CoffHdr *ch;
+	PE_DataDir *dd;
+	PE_OptHdr *oh;
+	PE_Scn *ps;
+	PE_SecHdr *sh;
+	unsigned p;
+	uint32_t reloc_rva, reloc_sz;
+	int i, reloc;
+
+	reloc = 0;
+	reloc_rva = reloc_sz = 0;
+
+	if (pe->pe_cmd == PE_C_RDWR) {
+		assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0);
+
+		if ((pe->pe_flags & LIBPE_F_DIRTY_COFF_HEADER) == 0 &&
+		    (pe->pe_flags & LIBPE_F_BAD_COFF_HEADER) == 0) {
+			if (lseek(pe->pe_fd, (off_t) sizeof(PE_CoffHdr),
+			    SEEK_CUR) < 0) {
+				errno = EIO;
+				return (-1);
+			}
+			off += sizeof(PE_CoffHdr);
+			assert(pe->pe_ch != NULL);
+			ch = pe->pe_ch;
+			goto coff_done;
+		}
+
+		/* lseek(2) to the offset of the COFF header. */
+		if (lseek(pe->pe_fd, off, SEEK_SET) < 0) {
+			errno = EIO;
+			return (-1);
+		}
+	}
+
+	if (pe->pe_ch == NULL) {
+		if ((ch = calloc(1, sizeof(PE_CoffHdr))) == NULL) {
+			errno = ENOMEM;
+			return (-1);
+		}
+		pe->pe_ch = ch;
+
+		/*
+		 * Default value for ch_machine if not provided by the
+		 * application.
+		 */
+		if (pe->pe_obj == PE_O_PE32P)
+			ch->ch_machine = IMAGE_FILE_MACHINE_AMD64;
+		else
+			ch->ch_machine = IMAGE_FILE_MACHINE_I386;
+
+	} else
+		ch = pe->pe_ch;
+
+	if (!ch->ch_timestamp)
+		ch->ch_timestamp = time(NULL);
+
+	if (pe->pe_obj == PE_O_PE32) {
+		if (!ch->ch_optsize)
+			ch->ch_optsize = PE_COFF_OPT_SIZE_32;
+		ch->ch_char |= IMAGE_FILE_EXECUTABLE_IMAGE |
+		    IMAGE_FILE_32BIT_MACHINE;
+	} else if (pe->pe_obj == PE_O_PE32P) {
+		if (!ch->ch_optsize)
+			ch->ch_optsize = PE_COFF_OPT_SIZE_32P;
+		ch->ch_char |= IMAGE_FILE_EXECUTABLE_IMAGE |
+		    IMAGE_FILE_LARGE_ADDRESS_AWARE;
+	} else
+		ch->ch_optsize = 0;
+
+	/*
+	 * COFF line number is deprecated by the PE/COFF
+	 * specification. COFF symbol table is deprecated
+	 * for executables.
+	 */
+	ch->ch_char |= IMAGE_FILE_LINE_NUMS_STRIPPED;
+	if (pe->pe_obj == PE_O_PE32 || pe->pe_obj == PE_O_PE32P)
+		ch->ch_char |= IMAGE_FILE_LOCAL_SYMS_STRIPPED;
+
+	ch->ch_nsec = pe->pe_nscn;
+
+	STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) {
+		sh = &ps->ps_sh;
+
+		if (ps->ps_ndx == 0xFFFFFFFFU) {
+			ch->ch_symptr = sh->sh_rawptr;
+			ch->ch_nsym = pe->pe_nsym;
+		}
+
+		if (pe->pe_obj == PE_O_PE32 || pe->pe_obj == PE_O_PE32P) {
+			if (ps->ps_ndx == (0xFFFF0000 | PE_DD_BASERELOC) ||
+			    strncmp(sh->sh_name, ".reloc", strlen(".reloc")) ==
+			    0) {
+				reloc = 1;
+				reloc_rva = sh->sh_addr;
+				reloc_sz = sh->sh_virtsize;
+			}
+		}
+	}
+
+	if (!reloc)
+		ch->ch_char |= IMAGE_FILE_RELOCS_STRIPPED;
+
+	if (pe->pe_flags & LIBPE_F_BAD_OPT_HEADER) {
+		if (pe->pe_obj == PE_O_PE32)
+			ch->ch_optsize = PE_COFF_OPT_SIZE_32;
+		else if (pe->pe_obj == PE_O_PE32P)
+			ch->ch_optsize = PE_COFF_OPT_SIZE_32P;
+		else
+			ch->ch_optsize = 0;
+	}
+
+	/*
+	 * Write the COFF header.
+	 */
+	hdr = tmp;
+	PE_WRITE16(hdr, ch->ch_machine);
+	PE_WRITE16(hdr, ch->ch_nsec);
+	PE_WRITE32(hdr, ch->ch_timestamp);
+	PE_WRITE32(hdr, ch->ch_symptr);
+	PE_WRITE32(hdr, ch->ch_nsym);
+	PE_WRITE16(hdr, ch->ch_optsize);
+	PE_WRITE16(hdr, ch->ch_char);
+	if (write(pe->pe_fd, tmp, sizeof(PE_CoffHdr)) !=
+	    (ssize_t) sizeof(PE_CoffHdr)) {
+		errno = EIO;
+		return (-1);
+	}
+
+coff_done:
+	off += sizeof(PE_CoffHdr);
+	pe->pe_flags &= ~LIBPE_F_DIRTY_COFF_HEADER;
+	pe->pe_flags &= ~LIBPE_F_BAD_COFF_HEADER;
+	pe->pe_flags |= LIBPE_F_DIRTY_SEC_HEADER;
+
+	if (ch->ch_optsize == 0)
+		return (off);
+
+	/*
+	 * Write the Optional header.
+	 */
+
+	if (pe->pe_cmd == PE_C_RDWR) {
+		if ((pe->pe_flags & LIBPE_F_DIRTY_OPT_HEADER) == 0 &&
+		    (pe->pe_flags & LIBPE_F_BAD_OPT_HEADER) == 0) {
+			if (lseek(pe->pe_fd, (off_t) ch->ch_optsize,
+			    SEEK_CUR) < 0) {
+				errno = EIO;
+				return (-1);
+			}
+			off += ch->ch_optsize;
+			return (off);
+		}
+
+	}
+
+	if (pe->pe_oh == NULL) {
+		if ((oh = calloc(1, sizeof(PE_OptHdr))) == NULL) {
+			errno = ENOMEM;
+			return (-1);
+		}
+		pe->pe_oh = oh;
+	} else
+		oh = pe->pe_oh;
+
+	if (pe->pe_obj == PE_O_PE32)
+		oh->oh_magic = PE_FORMAT_32;
+	else
+		oh->oh_magic = PE_FORMAT_32P;
+
+	/*
+	 * LinkerVersion should not be less than 2.5, which will cause
+	 * Windows to complain the executable is invalid in some case.
+	 * By default we set LinkerVersion to 2.22 (binutils 2.22)
+	 */
+	if (!oh->oh_ldvermajor && !oh->oh_ldverminor) {
+		oh->oh_ldvermajor = 2;
+		oh->oh_ldverminor = 22;
+	}
+
+	/*
+	 * The library always tries to write out all 16 data directories
+	 * but the actual data dir written will depend on ch_optsize.
+	 */
+	oh->oh_ndatadir = PE_DD_MAX;
+
+	if (!oh->oh_filealign)
+		oh->oh_filealign = 0x200;
+	if (!oh->oh_secalign)
+		oh->oh_secalign = 0x1000;
+	oh->oh_hdrsize = roundup(off + ch->ch_optsize + pe->pe_nscn *
+	    sizeof(PE_SecHdr), oh->oh_filealign);
+	oh->oh_imgsize = roundup(pe->pe_rvamax, oh->oh_secalign);
+
+#define WRITE_OPT(n)							\
+	do {								\
+		/*							\
+		 * Since the Optional Header size is variable, we must	\
+		 * check if the requested write size will overrun the	\
+		 * remaining header bytes.				\
+		 */							\
+		if (p + (n) > ch->ch_optsize) {				\
+			/* Pad the "extra" bytes */			\
+			if (libpe_pad(pe, ch->ch_optsize - p) < 0) {	\
+				errno = EIO;				\
+				return (-1);				\
+			}						\
+			goto opt_done;					\
+		}							\
+		if (write(pe->pe_fd, tmp, (n)) != (ssize_t) (n)) {	\
+			errno = EIO;					\
+			return (-1);					\
+		}							\
+		p += (n);						\
+	} while (0)
+#define	WRITE_OPT8(v) do { *tmp = (v); WRITE_OPT(1); } while(0)
+#define	WRITE_OPT16(v) do { le16enc(tmp, (v)); WRITE_OPT(2); } while(0)
+#define	WRITE_OPT32(v) do { le32enc(tmp, (v)); WRITE_OPT(4); } while(0)
+#define	WRITE_OPT64(v) do { le64enc(tmp, (v)); WRITE_OPT(8); } while(0)
+
+	p = 0;
+	WRITE_OPT16(oh->oh_magic);
+	if (oh->oh_magic == PE_FORMAT_32P)
+		pe->pe_obj = PE_O_PE32P;
+	WRITE_OPT8(oh->oh_ldvermajor);
+	WRITE_OPT8(oh->oh_ldverminor);
+	WRITE_OPT32(oh->oh_textsize);
+	WRITE_OPT32(oh->oh_datasize);
+	WRITE_OPT32(oh->oh_bsssize);
+	WRITE_OPT32(oh->oh_entry);
+	WRITE_OPT32(oh->oh_textbase);
+	if (oh->oh_magic != PE_FORMAT_32P) {
+		WRITE_OPT32(oh->oh_database);
+		WRITE_OPT32(oh->oh_imgbase);
+	} else
+		WRITE_OPT64(oh->oh_imgbase);
+	WRITE_OPT32(oh->oh_secalign);
+	WRITE_OPT32(oh->oh_filealign);
+	WRITE_OPT16(oh->oh_osvermajor);
+	WRITE_OPT16(oh->oh_osverminor);
+	WRITE_OPT16(oh->oh_imgvermajor);
+	WRITE_OPT16(oh->oh_imgverminor);
+	WRITE_OPT16(oh->oh_subvermajor);
+	WRITE_OPT16(oh->oh_subverminor);
+	WRITE_OPT32(oh->oh_win32ver);
+	WRITE_OPT32(oh->oh_imgsize);
+	WRITE_OPT32(oh->oh_hdrsize);
+	WRITE_OPT32(oh->oh_checksum);
+	WRITE_OPT16(oh->oh_subsystem);
+	WRITE_OPT16(oh->oh_dllchar);
+	if (oh->oh_magic != PE_FORMAT_32P) {
+		WRITE_OPT32(oh->oh_stacksizer);
+		WRITE_OPT32(oh->oh_stacksizec);
+		WRITE_OPT32(oh->oh_heapsizer);
+		WRITE_OPT32(oh->oh_heapsizec);
+	} else {
+		WRITE_OPT64(oh->oh_stacksizer);
+		WRITE_OPT64(oh->oh_stacksizec);
+		WRITE_OPT64(oh->oh_heapsizer);
+		WRITE_OPT64(oh->oh_heapsizec);
+	}
+	WRITE_OPT32(oh->oh_ldrflags);
+	WRITE_OPT32(oh->oh_ndatadir);
+
+	/*
+	 * Write the Data Directories.
+	 */
+
+	if (oh->oh_ndatadir > 0) {
+		if (pe->pe_dd == NULL) {
+			if ((dd = calloc(1, sizeof(PE_DataDir))) == NULL) {
+				errno = ENOMEM;
+				return (-1);
+			}
+			pe->pe_dd = dd;
+			dd->dd_total = PE_DD_MAX;
+		} else
+			dd = pe->pe_dd;
+
+		assert(oh->oh_ndatadir <= PE_DD_MAX);
+
+		if (reloc) {
+			dd->dd_e[PE_DD_BASERELOC].de_addr = reloc_rva;
+			dd->dd_e[PE_DD_BASERELOC].de_size = reloc_sz;
+		}
+
+		for (i = 0; (uint32_t) i < dd->dd_total; i++) {
+			WRITE_OPT32(dd->dd_e[i].de_addr);
+			WRITE_OPT32(dd->dd_e[i].de_size);
+		}
+	}
+
+	/* Pad the remaining bytes in the Optional header, if any. */
+	if (ch->ch_optsize > p) {
+		if (libpe_pad(pe, ch->ch_optsize - p) < 0) {
+			errno = EIO;
+			return (-1);
+		}
+	}
+
+opt_done:
+	off += ch->ch_optsize;
+	pe->pe_flags &= ~LIBPE_F_DIRTY_OPT_HEADER;
+	pe->pe_flags &= ~LIBPE_F_BAD_OPT_HEADER;
+	pe->pe_flags |= LIBPE_F_DIRTY_SEC_HEADER;
+
+	return (off);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libpe/libpe_dos.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,403 @@
+/*-
+ * Copyright (c) 2015 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: libpe_dos.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+int
+libpe_parse_msdos_header(PE *pe, char *hdr)
+{
+	PE_DosHdr *dh;
+	char coff[sizeof(PE_CoffHdr)];
+	uint32_t pe_magic;
+	int i;
+
+	if ((pe->pe_stub = malloc(sizeof(PE_DosHdr))) == NULL) {
+		errno = ENOMEM;
+		return (-1);
+	}
+	memcpy(pe->pe_stub, hdr, sizeof(PE_DosHdr));
+
+	if ((dh = malloc(sizeof(*dh))) == NULL) {
+		errno = ENOMEM;
+		return (-1);
+	}
+	pe->pe_dh = dh;
+
+	/* Read the conventional MS-DOS EXE header. */
+	memcpy(dh->dh_magic, hdr, 2);
+	hdr += 2;
+	PE_READ16(hdr, dh->dh_lastsize);
+	PE_READ16(hdr, dh->dh_nblock);
+	PE_READ16(hdr, dh->dh_nreloc);
+	PE_READ16(hdr, dh->dh_hdrsize);
+	PE_READ16(hdr, dh->dh_minalloc);
+	PE_READ16(hdr, dh->dh_maxalloc);
+	PE_READ16(hdr, dh->dh_ss);
+	PE_READ16(hdr, dh->dh_sp);
+	PE_READ16(hdr, dh->dh_checksum);
+	PE_READ16(hdr, dh->dh_ip);
+	PE_READ16(hdr, dh->dh_cs);
+	PE_READ16(hdr, dh->dh_relocpos);
+	PE_READ16(hdr, dh->dh_noverlay);
+
+	/* Do not continue if the EXE is not a PE/NE/... (new executable) */
+	if (dh->dh_relocpos != 0x40) {
+		pe->pe_flags |= LIBPE_F_BAD_DOS_HEADER;
+		return (0);
+	}
+
+	for (i = 0; i < 4; i++)
+		PE_READ16(hdr, dh->dh_reserved1[i]);
+	PE_READ16(hdr, dh->dh_oemid);
+	PE_READ16(hdr, dh->dh_oeminfo);
+	for (i = 0; i < 10; i++)
+		PE_READ16(hdr, dh->dh_reserved2[i]);
+	PE_READ32(hdr, dh->dh_lfanew);
+
+	/* Check if the e_lfanew pointer is valid. */
+	if (dh->dh_lfanew > pe->pe_fsize - 4) {
+		pe->pe_flags |= LIBPE_F_BAD_DOS_HEADER;
+		return (0);
+	}
+
+	if (dh->dh_lfanew < sizeof(PE_DosHdr) &&
+	    (pe->pe_flags & LIBPE_F_SPECIAL_FILE)) {
+		pe->pe_flags |= LIBPE_F_BAD_DOS_HEADER;
+		return (0);
+	}
+
+	if (dh->dh_lfanew > sizeof(PE_DosHdr)) {
+		pe->pe_stub_ex = dh->dh_lfanew - sizeof(PE_DosHdr);
+		if (pe->pe_flags & LIBPE_F_SPECIAL_FILE) {
+			/* Read in DOS stub now. */
+			if (libpe_read_msdos_stub(pe) < 0) {
+				pe->pe_flags |= LIBPE_F_BAD_DOS_HEADER;
+				return (0);
+			}
+		}
+	}
+
+	if ((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0) {
+		/* Jump to the PE header. */
+		if (lseek(pe->pe_fd, (off_t) dh->dh_lfanew, SEEK_SET) < 0) {
+			pe->pe_flags |= LIBPE_F_BAD_PE_HEADER;
+			return (0);
+		}
+	}
+
+	if (read(pe->pe_fd, &pe_magic, 4) != 4 ||
+	    htole32(pe_magic) != PE_SIGNATURE) {
+		pe->pe_flags |= LIBPE_F_BAD_PE_HEADER;
+		return (0);
+	}
+
+	if (read(pe->pe_fd, coff, sizeof(coff)) != (ssize_t) sizeof(coff)) {
+		pe->pe_flags |= LIBPE_F_BAD_COFF_HEADER;
+		return (0);
+	}
+
+	return (libpe_parse_coff_header(pe, coff));
+}
+
+int
+libpe_read_msdos_stub(PE *pe)
+{
+	void *m;
+
+	assert(pe->pe_stub_ex > 0 &&
+	    (pe->pe_flags & LIBPE_F_LOAD_DOS_STUB) == 0);
+
+	if ((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0) {
+		if (lseek(pe->pe_fd, (off_t) sizeof(PE_DosHdr), SEEK_SET) <
+		    0) {
+			errno = EIO;
+			goto fail;
+		}
+	}
+
+	if ((m = realloc(pe->pe_stub, sizeof(PE_DosHdr) + pe->pe_stub_ex)) ==
+	    NULL) {
+		errno = ENOMEM;
+		goto fail;
+	}
+	pe->pe_stub = m;
+
+	if (read(pe->pe_fd, pe->pe_stub + sizeof(PE_DosHdr), pe->pe_stub_ex) !=
+	    (ssize_t) pe->pe_stub_ex) {
+		errno = EIO;
+		goto fail;
+	}
+
+	pe->pe_flags |= LIBPE_F_LOAD_DOS_STUB;
+
+	/* Search for the Rich header embedded just before the PE header. */
+	(void) libpe_parse_rich_header(pe);
+
+	return (0);
+
+fail:
+	pe->pe_stub_ex = 0;
+
+	return (-1);
+}
+
+/*
+ * The "standard" MS-DOS stub displaying "This program cannot be run in
+ * DOS mode".
+ */
+static const char msdos_stub[] = {
+    '\x0e','\x1f','\xba','\x0e','\x00','\xb4','\x09','\xcd',
+    '\x21','\xb8','\x01','\x4c','\xcd','\x21','\x54','\x68',
+    '\x69','\x73','\x20','\x70','\x72','\x6f','\x67','\x72',
+    '\x61','\x6d','\x20','\x63','\x61','\x6e','\x6e','\x6f',
+    '\x74','\x20','\x62','\x65','\x20','\x72','\x75','\x6e',
+    '\x20','\x69','\x6e','\x20','\x44','\x4f','\x53','\x20',
+    '\x6d','\x6f','\x64','\x65','\x2e','\x0d','\x0d','\x0a',
+    '\x24','\x00','\x00','\x00','\x00','\x00','\x00','\x00',
+};
+
+static void
+init_dos_header(PE_DosHdr *dh)
+{
+
+	dh->dh_magic[0] = 'M';
+	dh->dh_magic[1] = 'Z';
+	dh->dh_lastsize = 144;
+	dh->dh_nblock = 3;
+	dh->dh_hdrsize = 4;
+	dh->dh_maxalloc = 65535;
+	dh->dh_sp = 184;
+	dh->dh_relocpos = 0x40;
+	dh->dh_lfanew = 0x80;
+}
+
+off_t
+libpe_write_msdos_stub(PE *pe, off_t off)
+{
+	PE_DosHdr *dh;
+	char tmp[sizeof(PE_DosHdr)], *hdr;
+	off_t d;
+	int i, strip_rich;
+
+	strip_rich = 0;
+
+	if (pe->pe_cmd == PE_C_RDWR) {
+		assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0);
+
+		if (pe->pe_dh != NULL &&
+		    (pe->pe_flags & PE_F_STRIP_DOS_STUB)) {
+			/*
+			 * If we strip MS-DOS stub, everything after it
+			 * needs rewritten.
+			 */
+			pe->pe_flags |= LIBPE_F_BAD_PE_HEADER;
+			goto done;
+		}
+
+		/*
+		 * lseek(2) to the PE signature if MS-DOS stub is not
+		 * modified.
+		 */
+		if (pe->pe_dh != NULL &&
+		    (pe->pe_flags & LIBPE_F_DIRTY_DOS_HEADER) == 0 &&
+		    (pe->pe_flags & LIBPE_F_BAD_DOS_HEADER) == 0 &&
+		    (pe->pe_flags & PE_F_STRIP_RICH_HEADER) == 0) {
+			if (lseek(pe->pe_fd,
+			    (off_t) (sizeof(PE_DosHdr) + pe->pe_stub_ex),
+			    SEEK_CUR) < 0) {
+				errno = EIO;
+				return (-1);
+			}
+			off = sizeof(PE_DosHdr) + pe->pe_stub_ex;
+			goto done;
+		}
+
+		/* Check if we should strip the Rich header. */
+		if (pe->pe_dh != NULL && pe->pe_stub_app == NULL &&
+		    (pe->pe_flags & LIBPE_F_BAD_DOS_HEADER) == 0 &&
+		    (pe->pe_flags & PE_F_STRIP_RICH_HEADER)) {
+			if ((pe->pe_flags & LIBPE_F_LOAD_DOS_STUB) == 0) {
+				(void) libpe_read_msdos_stub(pe);
+				if (lseek(pe->pe_fd, off, SEEK_SET) < 0) {
+					errno = EIO;
+					return (-1);
+				}
+			}
+			if (pe->pe_rh != NULL) {
+				strip_rich = 1;
+				pe->pe_flags |= LIBPE_F_DIRTY_DOS_HEADER;
+			}
+		}
+
+		/*
+		 * If length of MS-DOS stub will change, Mark the PE
+		 * signature is broken so that the PE signature and the
+		 * headers follow it will be rewritten.
+		 *
+		 * The sections should be loaded now since the stub might
+		 * overwrite the section data.
+		 */
+		if ((pe->pe_flags & LIBPE_F_BAD_DOS_HEADER) ||
+		    (pe->pe_stub_app != NULL && pe->pe_stub_app_sz !=
+			sizeof(PE_DosHdr) + pe->pe_stub_ex) || strip_rich) {
+			if (libpe_load_all_sections(pe) < 0)
+				return (-1);
+			if (lseek(pe->pe_fd, off, SEEK_SET) < 0) {
+				errno = EIO;
+				return (-1);
+			}
+			pe->pe_flags |= LIBPE_F_BAD_PE_HEADER;
+		}
+	}
+
+	if (pe->pe_flags & PE_F_STRIP_DOS_STUB)
+		goto done;
+
+	/* Always use application supplied MS-DOS stub, if exists. */
+	if (pe->pe_stub_app != NULL && pe->pe_stub_app_sz > 0) {
+		if (write(pe->pe_fd, pe->pe_stub_app, pe->pe_stub_app_sz) !=
+		    (ssize_t) pe->pe_stub_app_sz) {
+			errno = EIO;
+			return (-1);
+		}
+		off = pe->pe_stub_app_sz;
+		goto done;
+	}
+
+	/*
+	 * Write MS-DOS header.
+	 */
+
+	if (pe->pe_dh == NULL) {
+		if ((dh = calloc(1, sizeof(PE_DosHdr))) == NULL) {
+			errno = ENOMEM;
+			return (-1);
+		}
+		pe->pe_dh = dh;
+
+		init_dos_header(dh);
+
+		pe->pe_flags |= LIBPE_F_DIRTY_DOS_HEADER;
+	} else
+		dh = pe->pe_dh;
+
+	if (pe->pe_flags & LIBPE_F_BAD_DOS_HEADER)
+		init_dos_header(dh);
+
+	if (strip_rich) {
+		d = pe->pe_rh_start - pe->pe_stub;
+		dh->dh_lfanew = roundup(d, 8);
+	}
+
+	if ((pe->pe_flags & LIBPE_F_DIRTY_DOS_HEADER) ||
+	    (pe->pe_flags & LIBPE_F_BAD_DOS_HEADER)) {
+		memcpy(tmp, dh->dh_magic, 2);
+		hdr = tmp + 2;
+		PE_WRITE16(hdr, dh->dh_lastsize);
+		PE_WRITE16(hdr, dh->dh_nblock);
+		PE_WRITE16(hdr, dh->dh_nreloc);
+		PE_WRITE16(hdr, dh->dh_hdrsize);
+		PE_WRITE16(hdr, dh->dh_minalloc);
+		PE_WRITE16(hdr, dh->dh_maxalloc);
+		PE_WRITE16(hdr, dh->dh_ss);
+		PE_WRITE16(hdr, dh->dh_sp);
+		PE_WRITE16(hdr, dh->dh_checksum);
+		PE_WRITE16(hdr, dh->dh_ip);
+		PE_WRITE16(hdr, dh->dh_cs);
+		PE_WRITE16(hdr, dh->dh_relocpos);
+		PE_WRITE16(hdr, dh->dh_noverlay);
+		for (i = 0; i < 4; i++)
+			PE_WRITE16(hdr, dh->dh_reserved1[i]);
+		PE_WRITE16(hdr, dh->dh_oemid);
+		PE_WRITE16(hdr, dh->dh_oeminfo);
+		for (i = 0; i < 10; i++)
+			PE_WRITE16(hdr, dh->dh_reserved2[i]);
+		PE_WRITE32(hdr, dh->dh_lfanew);
+
+		if (write(pe->pe_fd, tmp, sizeof(tmp)) !=
+		    (ssize_t) sizeof(tmp)) {
+			errno = EIO;
+			return (-1);
+		}
+	} else {
+		assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0);
+		if (lseek(pe->pe_fd, (off_t) sizeof(PE_DosHdr), SEEK_CUR) <
+		    0) {
+			errno = EIO;
+			return (-1);
+		}
+	}
+
+	off = sizeof(PE_DosHdr);
+
+	/*
+	 * Write the MS-DOS stub.
+	 */
+
+	if (strip_rich) {
+		assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0);
+		assert(pe->pe_stub != NULL && pe->pe_rh_start != NULL);
+		d = pe->pe_rh_start - pe->pe_stub;
+		if (lseek(pe->pe_fd, d, SEEK_SET) < 0) {
+			errno = EIO;
+			return (-1);
+		}
+		off = d;
+		goto done;
+	}
+
+	if (pe->pe_cmd == PE_C_RDWR) {
+		if (lseek(pe->pe_fd, (off_t) pe->pe_stub_ex, SEEK_CUR) < 0) {
+			errno = EIO;
+			return (-1);
+		}
+		off += pe->pe_stub_ex;
+		goto done;
+	}
+
+	if (write(pe->pe_fd, msdos_stub, sizeof(msdos_stub)) !=
+	    (ssize_t) sizeof(msdos_stub)) {
+		errno = EIO;
+		return (-1);
+	}
+	off += sizeof(msdos_stub);
+
+done:
+	pe->pe_flags &= ~LIBPE_F_DIRTY_DOS_HEADER;
+	pe->pe_flags &= ~LIBPE_F_BAD_DOS_HEADER;
+
+	return (off);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libpe/libpe_init.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,145 @@
+/*-
+ * Copyright (c) 2015 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/stat.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: libpe_init.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+int
+libpe_open_object(PE *pe)
+{
+	struct stat sb;
+	mode_t mode;
+	char magic[sizeof(PE_DosHdr)];
+
+	if (fstat(pe->pe_fd, &sb) < 0)
+		return (-1);
+
+	mode = sb.st_mode;
+	pe->pe_fsize = (size_t) sb.st_size;
+
+	/* Reject unsupported file types. */
+	if (!S_ISREG(mode) && !S_ISCHR(mode) && !S_ISFIFO(mode) &&
+	    !S_ISSOCK(mode)) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	/* Read/Write mode is not supported for non-regular file. */
+	if (pe->pe_cmd == PE_C_RDWR && !S_ISREG(mode)) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	/* The minimal file should at least contain a COFF header. */
+	if (S_ISREG(mode) && pe->pe_fsize < sizeof(PE_CoffHdr)) {
+		errno = ENOENT;
+		return (-1);
+	}
+
+	/*
+	 * Search for MS-DOS header or COFF header.
+	 */
+
+	if (read(pe->pe_fd, magic, 2) != 2) {
+		errno = EIO;
+		return (-1);
+	}
+
+	if (magic[0] == 'M' && magic[1] == 'Z') {
+		pe->pe_obj = PE_O_PE32;
+		if (read(pe->pe_fd, &magic[2], sizeof(PE_DosHdr) - 2) !=
+		    (ssize_t) sizeof(PE_DosHdr) - 2) {
+			errno = EIO;
+			return (-1);
+		}
+		return (libpe_parse_msdos_header(pe, magic));
+
+	} else if (magic[0] == 'P' && magic[1] == 'E') {
+		if (read(pe->pe_fd, magic, 2) != 2) {
+			errno = EIO;
+			return (-1);
+		}
+		if (magic[0] == '\0' && magic[1] == '\0') {
+			pe->pe_obj = PE_O_PE32;
+			if (read(pe->pe_fd, magic, sizeof(PE_CoffHdr)) !=
+			    (ssize_t) sizeof(PE_CoffHdr)) {
+				errno = EIO;
+				return (-1);
+			}
+			return (libpe_parse_coff_header(pe, magic));
+		}
+		errno = ENOENT;
+		return (-1);
+
+	} else {
+		pe->pe_obj = PE_O_COFF;
+		if (read(pe->pe_fd, &magic[2], sizeof(PE_CoffHdr) - 2) !=
+		    (ssize_t) sizeof(PE_CoffHdr) - 2) {
+			errno = EIO;
+			return (-1);
+		}
+		return (libpe_parse_coff_header(pe, magic));
+	}
+}
+
+void
+libpe_release_object(PE *pe)
+{
+	PE_Scn *ps, *_ps;
+
+	if (pe->pe_dh)
+		free(pe->pe_dh);
+
+	if (pe->pe_rh) {
+		free(pe->pe_rh->rh_compid);
+		free(pe->pe_rh->rh_cnt);
+		free(pe->pe_rh);
+	}
+
+	if (pe->pe_ch)
+		free(pe->pe_ch);
+
+	if (pe->pe_oh)
+		free(pe->pe_oh);
+
+	if (pe->pe_dd)
+		free(pe->pe_dd);
+
+	if (pe->pe_stub)
+		free(pe->pe_stub);
+
+	STAILQ_FOREACH_SAFE(ps, &pe->pe_scn, ps_next, _ps)
+		libpe_release_scn(ps);
+
+	free(pe);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libpe/libpe_rich.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,128 @@
+/*-
+ * Copyright (c) 2015 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: libpe_rich.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+static char *
+memfind(char *s, const char *find, size_t slen, size_t flen)
+{
+	int i;
+
+	if (slen == 0 || flen == 0 || flen > slen)
+		return (NULL);
+
+	for (i = 0; (size_t) i <= slen - flen; i++) {
+		if (s[i] != find[0])
+			continue;
+		if (flen == 1)
+			return (&s[i]);
+		if (memcmp(&s[i + 1], &find[1], flen - 1) == 0)
+			return (&s[i]);
+	}
+
+	return (NULL);
+}
+
+int
+libpe_parse_rich_header(PE *pe)
+{
+	PE_RichHdr *rh;
+	char *p, *r, *s;
+	uint32_t x;
+	int found, i;
+
+	assert(pe->pe_stub != NULL && pe->pe_stub_ex > 0);
+
+	/* Search for the "Rich" keyword to locate the Rich header. */
+	s = pe->pe_stub + sizeof(PE_DosHdr);
+	r = memfind(s, PE_RICH_TEXT, pe->pe_stub_ex, 4);
+	if (r == NULL || r + 8 > s + pe->pe_stub_ex) {
+		errno = ENOENT;
+		return (-1);
+	}
+
+	if ((rh = calloc(1, sizeof(*rh))) == NULL) {
+		errno = ENOMEM;
+		return (-1);
+	}
+
+	rh->rh_xor = le32dec(r + 4); /* Retrieve the "XOR mask" */
+
+	/*
+	 * Search for the hidden keyword "DanS" by XOR the dwords before
+	 * the "Rich" keyword with the XOR mask.
+	 */
+	found = 0;
+	for (p = r - 4; p >= s; p -= 4) {
+		x = le32dec(p) ^ rh->rh_xor;
+		if (x == PE_RICH_HIDDEN) {
+			found = 1;
+			break;
+		}
+	}
+	if (!found) {
+		free(rh);
+		errno = ENOENT;
+		return (-1);
+	}
+
+	/*
+	 * Found the "DanS" keyword, which is the start of the Rich header.
+	 * The next step is to skip the first 16 bytes (DanS, XOR mask,
+	 * XOR mask, XOR mask) and read the (compid,cnt) tuples.
+	 */
+	pe->pe_rh_start = p;
+	p += 16;
+	rh->rh_total = (r - p) / 8;
+	if ((rh->rh_compid = malloc(rh->rh_total * sizeof(*rh->rh_compid))) ==
+	    NULL) {
+		free(rh);
+		errno = ENOMEM;
+		return (-1);
+	}
+	if ((rh->rh_cnt = malloc(rh->rh_total * sizeof(*rh->rh_cnt))) ==
+	    NULL) {
+		free(rh->rh_compid);
+		free(rh);
+		errno = ENOMEM;
+		return (-1);
+	}
+	for (i = 0; (uint32_t) i < rh->rh_total; i++, p += 8) {
+		rh->rh_compid[i] = le32dec(p) ^ rh->rh_xor;
+		rh->rh_cnt[i] = le32dec(p + 4) ^ rh->rh_xor;
+	}
+
+	pe->pe_rh = rh;
+
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libpe/libpe_section.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,518 @@
+/*-
+ * Copyright (c) 2016 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: libpe_section.c 3446 2016-05-03 01:31:17Z emaste $");
+
+PE_Scn *
+libpe_alloc_scn(PE *pe)
+{
+	PE_Scn *ps;
+
+	if ((ps = calloc(1, sizeof(PE_Scn))) == NULL) {
+		errno = ENOMEM;
+		return (NULL);
+	}
+	STAILQ_INIT(&ps->ps_b);
+	ps->ps_pe = pe;
+
+	return (ps);
+}
+
+void
+libpe_release_scn(PE_Scn *ps)
+{
+	PE *pe;
+	PE_SecBuf *sb, *_sb;
+
+	assert(ps != NULL);
+
+	pe = ps->ps_pe;
+
+	STAILQ_REMOVE(&pe->pe_scn, ps, _PE_Scn, ps_next);
+
+	STAILQ_FOREACH_SAFE(sb, &ps->ps_b, sb_next, _sb)
+		libpe_release_buffer(sb);
+
+	free(ps);
+}
+
+static int
+cmp_scn(PE_Scn *a, PE_Scn *b)
+{
+
+	if (a->ps_sh.sh_addr < b->ps_sh.sh_addr)
+		return (-1);
+	else if (a->ps_sh.sh_addr == b->ps_sh.sh_addr)
+		return (0);
+	else
+		return (1);
+}
+
+static void
+sort_sections(PE *pe)
+{
+
+	if (STAILQ_EMPTY(&pe->pe_scn))
+		return;
+
+	/* Sort the list of Scn by RVA in ascending order. */
+	STAILQ_SORT(&pe->pe_scn, _PE_Scn, ps_next, cmp_scn);
+}
+
+int
+libpe_parse_section_headers(PE *pe)
+{
+	char tmp[sizeof(PE_SecHdr)], *hdr;
+	PE_Scn *ps;
+	PE_SecHdr *sh;
+	PE_CoffHdr *ch;
+	PE_DataDir *dd;
+	int found, i;
+
+	assert(pe->pe_ch != NULL);
+
+	for (i = 0; (uint16_t) i < pe->pe_ch->ch_nsec; i++) {
+		if (read(pe->pe_fd, tmp, sizeof(PE_SecHdr)) !=
+		    (ssize_t) sizeof(PE_SecHdr)) {
+			pe->pe_flags |= LIBPE_F_BAD_SEC_HEADER;
+			return (0);
+		}
+
+		if ((ps = libpe_alloc_scn(pe)) == NULL)
+			return (-1);
+		STAILQ_INSERT_TAIL(&pe->pe_scn, ps, ps_next);
+		ps->ps_ndx = ++pe->pe_nscn;	/* Setion index is 1-based */
+		sh = &ps->ps_sh;
+
+		/*
+		 * Note that the section name won't be NUL-terminated if
+		 * its length happens to be 8.
+		 */
+		memcpy(sh->sh_name, tmp, sizeof(sh->sh_name));
+		hdr = tmp + 8;
+		PE_READ32(hdr, sh->sh_virtsize);
+		PE_READ32(hdr, sh->sh_addr);
+		PE_READ32(hdr, sh->sh_rawsize);
+		PE_READ32(hdr, sh->sh_rawptr);
+		PE_READ32(hdr, sh->sh_relocptr);
+		PE_READ32(hdr, sh->sh_lineptr);
+		PE_READ16(hdr, sh->sh_nreloc);
+		PE_READ16(hdr, sh->sh_nline);
+		PE_READ32(hdr, sh->sh_char);
+	}
+
+	/*
+	 * For all the data directories that don't belong to any section,
+	 * we create pseudo sections for them to make layout easier.
+	 */
+	dd = pe->pe_dd;
+	if (dd != NULL && dd->dd_total > 0) {
+		for (i = 0; (uint32_t) i < pe->pe_dd->dd_total; i++) {
+			if (dd->dd_e[i].de_size == 0)
+				continue;
+			found = 0;
+			STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) {
+				sh = &ps->ps_sh;
+				if (dd->dd_e[i].de_addr >= sh->sh_addr &&
+				    dd->dd_e[i].de_addr + dd->dd_e[i].de_size <=
+				    sh->sh_addr + sh->sh_virtsize) {
+					found = 1;
+					break;
+				}
+			}
+			if (found)
+				continue;
+
+			if ((ps = libpe_alloc_scn(pe)) == NULL)
+				return (-1);
+			STAILQ_INSERT_TAIL(&pe->pe_scn, ps, ps_next);
+			ps->ps_ndx = 0xFFFF0000U | i;
+			sh = &ps->ps_sh;
+			sh->sh_rawptr = dd->dd_e[i].de_addr; /* FIXME */
+			sh->sh_rawsize = dd->dd_e[i].de_size;
+		}
+	}
+
+	/*
+	 * Also consider the COFF symbol table as a pseudo section.
+	 */
+	ch = pe->pe_ch;
+	if (ch->ch_nsym > 0) {
+		if ((ps = libpe_alloc_scn(pe)) == NULL)
+			return (-1);
+		STAILQ_INSERT_TAIL(&pe->pe_scn, ps, ps_next);
+		ps->ps_ndx = 0xFFFFFFFFU;
+		sh = &ps->ps_sh;
+		sh->sh_rawptr = ch->ch_symptr;
+		sh->sh_rawsize = ch->ch_nsym * PE_SYM_ENTRY_SIZE;
+		pe->pe_nsym = ch->ch_nsym;
+	}
+
+	/* PE file headers initialization is complete if we reach here. */
+	return (0);
+}
+
+int
+libpe_load_section(PE *pe, PE_Scn *ps)
+{
+	PE_SecHdr *sh;
+	PE_SecBuf *sb;
+	size_t sz;
+	char tmp[4];
+
+	assert(pe != NULL && ps != NULL);
+	assert((ps->ps_flags & LIBPE_F_LOAD_SECTION) == 0);
+
+	sh = &ps->ps_sh;
+
+	/* Allocate a PE_SecBuf struct without buffer for empty sections. */
+	if (sh->sh_rawsize == 0) {
+		(void) libpe_alloc_buffer(ps, 0);
+		ps->ps_flags |= LIBPE_F_LOAD_SECTION;
+		return (0);
+	}
+
+	if ((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0) {
+		if (lseek(pe->pe_fd, (off_t) sh->sh_rawptr, SEEK_SET) < 0) {
+			errno = EIO;
+			return (-1);
+		}
+	}
+
+	if ((sb = libpe_alloc_buffer(ps, sh->sh_rawsize)) == NULL)
+		return (-1);
+
+	if (read(pe->pe_fd, sb->sb_pb.pb_buf, sh->sh_rawsize) !=
+	    (ssize_t) sh->sh_rawsize) {
+		errno = EIO;
+		return (-1);
+	}
+
+	if (ps->ps_ndx == 0xFFFFFFFFU) {
+		/*
+		 * Index 0xFFFFFFFF indicates this section is a pseudo
+		 * section that contains the COFF symbol table. We should
+		 * read in the string table right after it.
+		 */
+		if (read(pe->pe_fd, tmp, sizeof(tmp)) !=
+		    (ssize_t) sizeof(tmp)) {
+			errno = EIO;
+			return (-1);
+		}
+		sz = le32dec(tmp);
+
+		/*
+		 * The minimum value for the size field is 4, which indicates
+		 * there is no string table.
+		 */
+		if (sz > 4) {
+			sz -= 4;
+			if ((sb = libpe_alloc_buffer(ps, sz)) == NULL)
+				return (-1);
+			if (read(pe->pe_fd, sb->sb_pb.pb_buf, sz) !=
+			    (ssize_t) sz) {
+				errno = EIO;
+				return (-1);
+			}
+		}
+	}
+
+	ps->ps_flags |= LIBPE_F_LOAD_SECTION;
+
+	return (0);
+}
+
+int
+libpe_load_all_sections(PE *pe)
+{
+	PE_Scn *ps;
+	PE_SecHdr *sh;
+	unsigned r, s;
+	off_t off;
+	char tmp[256];
+
+	/* Calculate the current offset into the file. */
+	off = 0;
+	if (pe->pe_dh != NULL)
+		off += pe->pe_dh->dh_lfanew + 4;
+	if (pe->pe_ch != NULL)
+		off += sizeof(PE_CoffHdr) + pe->pe_ch->ch_optsize;
+
+	STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) {
+		if (ps->ps_flags & LIBPE_F_LOAD_SECTION)
+			continue;
+		sh = &ps->ps_sh;
+
+		/*
+		 * For special files, we consume the padding in between
+		 * and advance to the section offset.
+		 */
+		if (pe->pe_flags & LIBPE_F_SPECIAL_FILE) {
+			/* Can't go backwards. */
+			if (off > sh->sh_rawptr) {
+				errno = EIO;
+				return (-1);
+			}
+			if (off < sh->sh_rawptr) {
+				r = sh->sh_rawptr - off;
+				for (; r > 0; r -= s) {
+					s = r > sizeof(tmp) ? sizeof(tmp) : r;
+					if (read(pe->pe_fd, tmp, s) !=
+					    (ssize_t) s) {
+						errno = EIO;
+						return (-1);
+					}
+				}
+			}
+		}
+
+		/* Load the section content. */
+		if (libpe_load_section(pe, ps) < 0)
+			return (-1);
+	}
+
+	return (0);
+}
+
+int
+libpe_resync_sections(PE *pe, off_t off)
+{
+	PE_Scn *ps;
+	PE_SecHdr *sh;
+	size_t falign, nsec;
+
+	/* Firstly, sort all sections by their file offsets. */
+	sort_sections(pe);
+
+	/* Count the number of sections. */
+	nsec = 0;
+	STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) {
+		if (ps->ps_flags & LIBPE_F_STRIP_SECTION)
+			continue;
+		if (ps->ps_ndx & 0xFFFF0000U)
+			continue;
+		nsec++;
+	}
+	pe->pe_nscn = nsec;
+
+	/*
+	 * Calculate the file offset for the first section. (`off' is
+	 * currently pointing to the COFF header.)
+	 */
+	off += sizeof(PE_CoffHdr);
+	if (pe->pe_ch != NULL && pe->pe_ch->ch_optsize > 0)
+		off += pe->pe_ch->ch_optsize;
+	else {
+		switch (pe->pe_obj) {
+		case PE_O_PE32:
+			off += PE_COFF_OPT_SIZE_32;
+			break;
+		case PE_O_PE32P:
+			off += PE_COFF_OPT_SIZE_32P;
+			break;
+		case PE_O_COFF:
+		default:
+			break;
+		}
+	}
+	off += nsec * sizeof(PE_SecHdr);
+
+	/*
+	 * Determine the file alignment for sections.
+	 */
+	if (pe->pe_oh != NULL && pe->pe_oh->oh_filealign > 0)
+		falign = pe->pe_oh->oh_filealign;
+	else {
+		/*
+		 * Use the default file alignment defined by the
+		 * PE/COFF specification.
+		 */
+		if (pe->pe_obj == PE_O_COFF)
+			falign = 4;
+		else
+			falign = 512;
+	}
+
+	/*
+	 * Step through each section (and pseduo section) and verify
+	 * alignment constraint and overlapping, make adjustment if need.
+	 */
+	pe->pe_rvamax = 0;
+	STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) {
+		if (ps->ps_flags & LIBPE_F_STRIP_SECTION)
+			continue;
+
+		sh = &ps->ps_sh;
+
+		if (sh->sh_addr + sh->sh_virtsize > pe->pe_rvamax)
+			pe->pe_rvamax = sh->sh_addr + sh->sh_virtsize;
+
+		if (ps->ps_ndx & 0xFFFF0000U)
+			ps->ps_falign = 4;
+		else
+			ps->ps_falign = falign;
+
+		off = roundup(off, ps->ps_falign);
+
+		if (off != sh->sh_rawptr)
+			ps->ps_flags |= PE_F_DIRTY;
+
+		if (ps->ps_flags & PE_F_DIRTY) {
+			if ((ps->ps_flags & LIBPE_F_LOAD_SECTION) == 0) {
+				if (libpe_load_section(pe, ps) < 0)
+					return (-1);
+			}
+			sh->sh_rawsize = libpe_resync_buffers(ps);
+		}
+
+		/*
+		 * Sections only contains uninitialized data should set
+		 * PointerToRawData to zero according to the PE/COFF
+		 * specification.
+		 */
+		if (sh->sh_rawsize == 0)
+			sh->sh_rawptr = 0;
+		else
+			sh->sh_rawptr = off;
+
+		off += sh->sh_rawsize;
+	}
+
+	return (0);
+}
+
+off_t
+libpe_write_section_headers(PE *pe, off_t off)
+{
+	char tmp[sizeof(PE_SecHdr)], *hdr;
+	PE_Scn *ps;
+	PE_SecHdr *sh;
+
+	if (pe->pe_flags & LIBPE_F_BAD_SEC_HEADER || pe->pe_nscn == 0)
+		return (off);
+
+	if ((pe->pe_flags & LIBPE_F_DIRTY_SEC_HEADER) == 0) {
+		off += sizeof(PE_SecHdr) * pe->pe_ch->ch_nsec;
+		return (off);
+	}
+
+	STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) {
+		if (ps->ps_flags & LIBPE_F_STRIP_SECTION)
+			continue;
+		if (ps->ps_ndx & 0xFFFF0000U)
+			continue;
+		if ((pe->pe_flags & LIBPE_F_DIRTY_SEC_HEADER) == 0 &&
+		    (ps->ps_flags & PE_F_DIRTY) == 0)
+			goto next_header;
+
+		sh = &ps->ps_sh;
+
+		memcpy(tmp, sh->sh_name, sizeof(sh->sh_name));
+		hdr = tmp + 8;
+		PE_WRITE32(hdr, sh->sh_virtsize);
+		PE_WRITE32(hdr, sh->sh_addr);
+		PE_WRITE32(hdr, sh->sh_rawsize);
+		PE_WRITE32(hdr, sh->sh_rawptr);
+		PE_WRITE32(hdr, sh->sh_relocptr);
+		PE_WRITE32(hdr, sh->sh_lineptr);
+		PE_WRITE16(hdr, sh->sh_nreloc);
+		PE_WRITE16(hdr, sh->sh_nline);
+		PE_WRITE32(hdr, sh->sh_char);
+
+		if (write(pe->pe_fd, tmp, sizeof(PE_SecHdr)) !=
+		    (ssize_t) sizeof(PE_SecHdr)) {
+			errno = EIO;
+			return (-1);
+		}
+
+	next_header:
+		off += sizeof(PE_SecHdr);
+	}
+
+	return (off);
+}
+
+off_t
+libpe_write_sections(PE *pe, off_t off)
+{
+	PE_Scn *ps;
+	PE_SecHdr *sh;
+
+	if (pe->pe_flags & LIBPE_F_BAD_SEC_HEADER)
+		return (off);
+
+	STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) {
+		sh = &ps->ps_sh;
+
+		if (ps->ps_flags & LIBPE_F_STRIP_SECTION)
+			continue;
+
+		/* Skip empty sections. */
+		if (sh->sh_rawptr == 0 || sh->sh_rawsize == 0)
+			continue;
+
+		/*
+		 * Padding between sections. (padding always written
+		 * in case the the section headers or sections are
+		 * moved or shrunk.)
+		 */
+		assert(off <= sh->sh_rawptr);
+		if (off < sh->sh_rawptr)
+			libpe_pad(pe, sh->sh_rawptr - off);
+
+		if ((ps->ps_flags & PE_F_DIRTY) == 0) {
+			assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0);
+			if (lseek(pe->pe_fd,
+			    (off_t) (sh->sh_rawptr + sh->sh_rawsize),
+			    SEEK_SET) < 0) {
+				errno = EIO;
+				return (-1);
+			}
+			off = sh->sh_rawptr + sh->sh_rawsize;
+			continue;
+		}
+
+		off = sh->sh_rawptr;
+
+		if (libpe_write_buffers(ps) < 0)
+			return (-1);
+
+		off += sh->sh_rawsize;
+
+		ps->ps_flags &= ~PE_F_DIRTY;
+	}
+
+	return (off);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libpe/libpe_utils.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,69 @@
+/*-
+ * Copyright (c) 2016 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: libpe_utils.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+off_t
+libpe_align(PE *pe, off_t off, size_t align)
+{
+	off_t n;
+
+	assert(align > 0 && (align & (align - 1)) == 0);
+
+	n = roundup(off, align);
+	if (n > off) {
+		if (libpe_pad(pe, n - off) < 0)
+			return (-1);
+	}
+
+	return (n);
+}
+
+int
+libpe_pad(PE *pe, size_t pad)
+{
+	char tmp[128];
+	size_t s;
+
+	memset(tmp, 0, sizeof(tmp));
+	for (; pad > 0; pad -= s) {
+		s = pad > sizeof(tmp) ? sizeof(tmp) : pad;
+		if (write(pe->pe_fd, tmp, s) != (ssize_t) s) {
+			errno = EIO;
+			return (-1);
+		}
+	}
+
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libpe/os.Linux.mk	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,6 @@
+# $Id: os.Linux.mk 3312 2016-01-10 09:23:51Z kaiwang27 $
+
+CFLAGS+=	-Wall -Wno-unused-parameter -Wstrict-prototypes \
+		-Wmissing-prototypes -Wpointer-arith -Wreturn-type \
+		-Wcast-qual -Wwrite-strings -Wswitch -Wshadow \
+		-Wcast-align -Wunused-parameter
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libpe/os.NetBSD.mk	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,2 @@
+# TODO(#511): Revert after the source tree is -Wconversion clean.
+WARNS=5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libpe/pe.h	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,295 @@
+/*-
+ * Copyright (c) 2015 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: pe.h 3441 2016-04-07 15:04:20Z emaste $
+ */
+
+#ifndef	_PE_H_
+#define	_PE_H_
+
+#include <stdint.h>
+
+/*
+ * MS-DOS header.
+ */
+
+typedef struct _PE_DosHdr {
+	char dh_magic[2];
+	uint16_t dh_lastsize;
+	uint16_t dh_nblock;
+	uint16_t dh_nreloc;
+	uint16_t dh_hdrsize;
+	uint16_t dh_minalloc;
+	uint16_t dh_maxalloc;
+	uint16_t dh_ss;
+	uint16_t dh_sp;
+	uint16_t dh_checksum;
+	uint16_t dh_ip;
+	uint16_t dh_cs;
+	uint16_t dh_relocpos;
+	uint16_t dh_noverlay;
+	uint16_t dh_reserved1[4];
+	uint16_t dh_oemid;
+	uint16_t dh_oeminfo;
+	uint16_t dh_reserved2[10];
+	uint32_t dh_lfanew;
+} PE_DosHdr;
+
+/*
+ * Rich header.
+ */
+
+typedef struct _PE_RichHdr {
+	uint32_t rh_xor;
+	uint32_t rh_total;
+	uint32_t *rh_compid;
+	uint32_t *rh_cnt;
+} PE_RichHdr;
+
+/*
+ * COFF header: Machine Types.
+ */
+
+#define	IMAGE_FILE_MACHINE_UNKNOWN	0x0	/* not specified */
+#define	IMAGE_FILE_MACHINE_AM33		0x1d3	/* Matsushita AM33 */
+#define	IMAGE_FILE_MACHINE_AMD64	0x8664	/* x86-64 */
+#define	IMAGE_FILE_MACHINE_ARM		0x1c0	/* ARM LE */
+#define	IMAGE_FILE_MACHINE_ARMNT	0x1c4	/* ARMv7(or higher) Thumb */
+#define	IMAGE_FILE_MACHINE_ARM64	0xaa64	/* ARMv8 64-bit */
+#define	IMAGE_FILE_MACHINE_EBC		0xebc	/* EFI byte code */
+#define	IMAGE_FILE_MACHINE_I386		0x14c	/* x86 */
+#define	IMAGE_FILE_MACHINE_IA64		0x200	/* IA64 */
+#define	IMAGE_FILE_MACHINE_M32R		0x9041	/* Mitsubishi M32R LE */
+#define	IMAGE_FILE_MACHINE_MIPS16	0x266	/* MIPS16 */
+#define	IMAGE_FILE_MACHINE_MIPSFPU	0x366	/* MIPS with FPU */
+#define	IMAGE_FILE_MACHINE_MIPSFPU16	0x466	/* MIPS16 with FPU */
+#define	IMAGE_FILE_MACHINE_POWERPC	0x1f0	/* Power PC LE */
+#define	IMAGE_FILE_MACHINE_POWERPCFP	0x1f1	/* Power PC floating point */
+#define	IMAGE_FILE_MACHINE_R4000	0x166	/* MIPS R4000 LE */
+#define	IMAGE_FILE_MACHINE_RISCV32	0x5032	/* RISC-V 32-bit */
+#define	IMAGE_FILE_MACHINE_RISCV64	0x5064	/* RISC-V 64-bit */
+#define	IMAGE_FILE_MACHINE_RISCV128	0x5128	/* RISC-V 128-bit */
+#define	IMAGE_FILE_MACHINE_SH3		0x1a2	/* Hitachi SH3 */
+#define	IMAGE_FILE_MACHINE_SH3DSP	0x1a3	/* Hitachi SH3 DSP */
+#define	IMAGE_FILE_MACHINE_SH4		0x1a6	/* Hitachi SH4 */
+#define	IMAGE_FILE_MACHINE_SH5		0x1a8	/* Hitachi SH5 */
+#define	IMAGE_FILE_MACHINE_THUMB	0x1c2	/* ARM or Thumb interworking */
+#define	IMAGE_FILE_MACHINE_WCEMIPSV2	0x169	/* MIPS LE WCE v2 */
+
+/*
+ * COFF header: Characteristics
+ */
+
+#define	IMAGE_FILE_RELOCS_STRIPPED		0x0001
+#define	IMAGE_FILE_EXECUTABLE_IMAGE		0x0002
+#define	IMAGE_FILE_LINE_NUMS_STRIPPED		0x0004
+#define	IMAGE_FILE_LOCAL_SYMS_STRIPPED		0x0008
+#define	IMAGE_FILE_AGGRESSIVE_WS_TRIM		0x0010
+#define	IMAGE_FILE_LARGE_ADDRESS_AWARE		0x0020
+#define	IMAGE_FILE_BYTES_REVERSED_LO		0x0080
+#define	IMAGE_FILE_32BIT_MACHINE		0x0100
+#define	IMAGE_FILE_DEBUG_STRIPPED		0x0200
+#define	IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP	0x0400
+#define	IMAGE_FILE_NET_RUN_FROM_SWAP		0x0800
+#define	IMAGE_FILE_SYSTEM			0x1000
+#define	IMAGE_FILE_DLL				0x2000
+#define	IMAGE_FILE_UP_SYSTEM_ONLY		0x4000
+#define	IMAGE_FILE_BYTES_REVERSED_HI		0x8000
+
+/*
+ * COFF Header.
+ */
+
+typedef struct _PE_CoffHdr {
+	uint16_t ch_machine;
+	uint16_t ch_nsec;
+	uint32_t ch_timestamp;
+	uint32_t ch_symptr;
+	uint32_t ch_nsym;
+	uint16_t ch_optsize;
+	uint16_t ch_char;
+} PE_CoffHdr;
+
+
+/*
+ * Optional Header: Subsystem.
+ */
+
+#define	IMAGE_SUBSYSTEM_UNKNOWN			0
+#define	IMAGE_SUBSYSTEM_NATIVE			1
+#define	IMAGE_SUBSYSTEM_WINDOWS_GUI		2
+#define	IMAGE_SUBSYSTEM_WINDOWS_CUI		3
+#define	IMAGE_SUBSYSTEM_POSIX_CUI		7
+#define	IMAGE_SUBSYSTEM_WINDOWS_CE_GUI		9
+#define	IMAGE_SUBSYSTEM_EFI_APPLICATION		10
+#define	IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER	11
+#define	IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER	12
+#define	IMAGE_SUBSYSTEM_EFI_ROM			13
+#define	IMAGE_SUBSYSTEM_XBOX			14
+
+/*
+ * Optional Header: DLL Characteristics
+ */
+
+#define	IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE		0x0040
+#define	IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY	0x0080
+#define	IMAGE_DLL_CHARACTERISTICS_NX_COMPAT		0x0100
+#define	IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION		0x0200
+#define	IMAGE_DLL_CHARACTERISTICS_NO_SEH		0x0400
+#define	IMAGE_DLL_CHARACTERISTICS_NO_BIND		0x0800
+#define	IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER		0x2000
+#define	IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE	0x8000
+
+/*
+ * Optional Header.
+ */
+
+#define	PE_FORMAT_ROM		0x107
+#define	PE_FORMAT_32		0x10b
+#define	PE_FORMAT_32P		0x20b
+
+typedef struct _PE_OptHdr {
+	uint16_t oh_magic;
+	uint8_t oh_ldvermajor;
+	uint8_t oh_ldverminor;
+	uint32_t oh_textsize;
+	uint32_t oh_datasize;
+	uint32_t oh_bsssize;
+	uint32_t oh_entry;
+	uint32_t oh_textbase;
+	uint32_t oh_database;
+	uint64_t oh_imgbase;
+	uint32_t oh_secalign;
+	uint32_t oh_filealign;
+	uint16_t oh_osvermajor;
+	uint16_t oh_osverminor;
+	uint16_t oh_imgvermajor;
+	uint16_t oh_imgverminor;
+	uint16_t oh_subvermajor;
+	uint16_t oh_subverminor;
+	uint32_t oh_win32ver;
+	uint32_t oh_imgsize;
+	uint32_t oh_hdrsize;
+	uint32_t oh_checksum;
+	uint16_t oh_subsystem;
+	uint16_t oh_dllchar;
+	uint64_t oh_stacksizer;
+	uint64_t oh_stacksizec;
+	uint64_t oh_heapsizer;
+	uint64_t oh_heapsizec;
+	uint32_t oh_ldrflags;
+	uint32_t oh_ndatadir;
+} PE_OptHdr;
+
+/*
+ * Optional Header: Data Directories.
+ */
+
+#define	PE_DD_EXPORT		0
+#define	PE_DD_IMPORT		1
+#define	PE_DD_RESROUCE		2
+#define	PE_DD_EXCEPTION		3
+#define	PE_DD_CERTIFICATE	4
+#define	PE_DD_BASERELOC		5
+#define	PE_DD_DEBUG		6
+#define	PE_DD_ARCH		7
+#define	PE_DD_GLOBALPTR		8
+#define	PE_DD_TLS		9
+#define	PE_DD_LOADCONFIG	10
+#define	PE_DD_BOUNDIMPORT	11
+#define	PE_DD_IAT		12
+#define	PE_DD_DELAYIMPORT	13
+#define	PE_DD_CLRRUNTIME	14
+#define	PE_DD_RESERVED		15
+#define	PE_DD_MAX		16
+
+typedef struct _PE_DataDirEntry {
+	uint32_t de_addr;
+	uint32_t de_size;
+} PE_DataDirEntry;
+
+typedef struct _PE_DataDir {
+	PE_DataDirEntry dd_e[PE_DD_MAX];
+	uint32_t dd_total;
+} PE_DataDir;
+
+/*
+ * Section Headers: Section flags.
+ */
+
+#define	IMAGE_SCN_TYPE_NO_PAD			0x00000008
+#define	IMAGE_SCN_CNT_CODE			0x00000020
+#define	IMAGE_SCN_CNT_INITIALIZED_DATA		0x00000040
+#define	IMAGE_SCN_CNT_UNINITIALIZED_DATA	0x00000080
+#define	IMAGE_SCN_LNK_OTHER			0x00000100
+#define	IMAGE_SCN_LNK_INFO			0x00000200
+#define	IMAGE_SCN_LNK_REMOVE			0x00000800
+#define	IMAGE_SCN_LNK_COMDAT			0x00001000
+#define	IMAGE_SCN_GPREL				0x00008000
+#define	IMAGE_SCN_MEM_PURGEABLE			0x00020000
+#define	IMAGE_SCN_MEM_16BIT			0x00020000
+#define	IMAGE_SCN_MEM_LOCKED			0x00040000
+#define	IMAGE_SCN_MEM_PRELOAD			0x00080000
+#define	IMAGE_SCN_ALIGN_1BYTES			0x00100000
+#define	IMAGE_SCN_ALIGN_2BYTES			0x00200000
+#define	IMAGE_SCN_ALIGN_4BYTES			0x00300000
+#define	IMAGE_SCN_ALIGN_8BYTES			0x00400000
+#define	IMAGE_SCN_ALIGN_16BYTES			0x00500000
+#define	IMAGE_SCN_ALIGN_32BYTES			0x00600000
+#define	IMAGE_SCN_ALIGN_64BYTES			0x00700000
+#define	IMAGE_SCN_ALIGN_128BYTES		0x00800000
+#define	IMAGE_SCN_ALIGN_256BYTES		0x00900000
+#define	IMAGE_SCN_ALIGN_512BYTES		0x00A00000
+#define	IMAGE_SCN_ALIGN_1024BYTES		0x00B00000
+#define	IMAGE_SCN_ALIGN_2048BYTES		0x00C00000
+#define	IMAGE_SCN_ALIGN_4096BYTES		0x00D00000
+#define	IMAGE_SCN_ALIGN_8192BYTES		0x00E00000
+#define	IMAGE_SCN_LNK_NRELOC_OVFL		0x01000000
+#define	IMAGE_SCN_MEM_DISCARDABLE		0x02000000
+#define	IMAGE_SCN_MEM_NOT_CACHED		0x04000000
+#define	IMAGE_SCN_MEM_NOT_PAGED			0x08000000
+#define	IMAGE_SCN_MEM_SHARED			0x10000000
+#define	IMAGE_SCN_MEM_EXECUTE			0x20000000
+#define	IMAGE_SCN_MEM_READ			0x40000000
+#define	IMAGE_SCN_MEM_WRITE			0x80000000
+
+/*
+ * Section Headers.
+ */
+
+typedef struct _PE_SecHdr {
+	char sh_name[8];
+	uint32_t sh_virtsize;
+	uint32_t sh_addr;
+	uint32_t sh_rawsize;
+	uint32_t sh_rawptr;
+	uint32_t sh_relocptr;
+	uint32_t sh_lineptr;
+	uint16_t sh_nreloc;
+	uint16_t sh_nline;
+	uint32_t sh_char;
+} PE_SecHdr;
+
+#endif	/* !_PE_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libpe/pe_buffer.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,100 @@
+/*-
+ * Copyright (c) 2016 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: pe_buffer.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+PE_Buffer *
+pe_getbuffer(PE_Scn *ps, PE_Buffer *pb)
+{
+	PE *pe;
+	PE_SecBuf *sb;
+
+	if (ps == NULL) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	pe = ps->ps_pe;
+
+	if ((ps->ps_flags & LIBPE_F_LOAD_SECTION) == 0) {
+		if (pe->pe_flags & LIBPE_F_FD_DONE) {
+			errno = EACCES;
+			return (NULL);
+		}
+		if (pe->pe_flags & LIBPE_F_SPECIAL_FILE) {
+			if (libpe_load_all_sections(pe) < 0)
+				return (NULL);
+		} else {
+			if (libpe_load_section(pe, ps) < 0)
+				return (NULL);
+		}
+	}
+
+	sb = (PE_SecBuf *) pb;
+
+	if (sb == NULL)
+		sb = STAILQ_FIRST(&ps->ps_b);
+	else
+		sb = STAILQ_NEXT(sb, sb_next);
+
+	return ((PE_Buffer *) sb);
+}
+
+PE_Buffer *
+pe_newbuffer(PE_Scn *ps)
+{
+	PE *pe;
+	PE_SecBuf *sb;
+
+	if (ps == NULL) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	pe = ps->ps_pe;
+
+	if (pe->pe_flags & LIBPE_F_FD_DONE) {
+		errno = EACCES;
+		return (NULL);
+	}
+
+	if ((ps->ps_flags & LIBPE_F_LOAD_SECTION) == 0) {
+		if (libpe_load_section(pe, ps) < 0)
+			return (NULL);
+	}
+
+	if ((sb = libpe_alloc_buffer(ps, 0)) == NULL)
+		return (NULL);
+
+	sb->sb_flags |= PE_F_DIRTY;
+	ps->ps_flags |= PE_F_DIRTY;
+
+	return ((PE_Buffer *) sb);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libpe/pe_cntl.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 2016 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: pe_cntl.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+int
+pe_cntl(PE *pe, PE_Cmd cmd)
+{
+
+	if (pe == NULL) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	switch (cmd) {
+	case PE_C_FDDONE:
+		pe->pe_flags |= LIBPE_F_FD_DONE;
+		break;
+
+	case PE_C_FDREAD:
+		if (pe->pe_cmd == PE_C_WRITE) {
+			errno = EACCES;
+			return (-1);
+		}
+		if (libpe_load_all_sections(pe) < 0)
+			return (-1);
+		break;
+
+	default:
+		errno = EINVAL;
+		return (-1);
+	}
+
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libpe/pe_coff.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,157 @@
+/*-
+ * Copyright (c) 2015 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: pe_coff.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+PE_CoffHdr *
+pe_coff_header(PE *pe)
+{
+
+	if (pe->pe_ch == NULL) {
+		errno = ENOENT;
+		return (NULL);
+	}
+
+	return (pe->pe_ch);
+}
+
+PE_OptHdr *
+pe_opt_header(PE *pe)
+{
+
+	if (pe->pe_oh == NULL) {
+		errno = ENOENT;
+		return (NULL);
+	}
+
+	return (pe->pe_oh);
+}
+
+PE_DataDir *
+pe_data_dir(PE *pe)
+{
+
+	if (pe->pe_dd == NULL) {
+		errno = ENOENT;
+		return (NULL);
+	}
+
+	return (pe->pe_dd);
+}
+
+int
+pe_update_coff_header(PE *pe, PE_CoffHdr *ch)
+{
+
+	if (pe == NULL || ch == NULL) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) {
+		errno = EACCES;
+		return (-1);
+	}
+
+	if (pe->pe_ch == NULL) {
+		if ((pe->pe_ch = malloc(sizeof(PE_CoffHdr))) == NULL) {
+			errno = ENOMEM;
+			return (-1);
+		}
+	} else {
+		/* Rewrite optional header if `optsize' field changed. */
+		if (pe->pe_ch->ch_optsize != ch->ch_optsize)
+			pe->pe_flags |= LIBPE_F_DIRTY_OPT_HEADER;
+	}
+
+	*pe->pe_ch = *ch;
+
+	pe->pe_flags |= LIBPE_F_DIRTY_COFF_HEADER;
+
+	return (0);
+}
+
+int
+pe_update_opt_header(PE *pe, PE_OptHdr *oh)
+{
+
+	if (pe == NULL || oh == NULL) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) {
+		errno = EACCES;
+		return (-1);
+	}
+
+	if (pe->pe_oh == NULL) {
+		if ((pe->pe_oh = malloc(sizeof(PE_OptHdr))) == NULL) {
+			errno = ENOMEM;
+			return (-1);
+		}
+	}
+
+	*pe->pe_oh = *oh;
+
+	pe->pe_flags |= LIBPE_F_DIRTY_OPT_HEADER;
+
+	return (0);
+}
+
+int
+pe_update_data_dir(PE *pe, PE_DataDir *dd)
+{
+
+	if (pe == NULL || dd == NULL) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) {
+		errno = EACCES;
+		return (-1);
+	}
+
+	if (pe->pe_dd == NULL) {
+		if ((pe->pe_dd = malloc(sizeof(PE_DataDir))) == NULL) {
+			errno = ENOMEM;
+			return (-1);
+		}
+	}
+
+	*pe->pe_dd = *dd;
+
+	pe->pe_flags |= LIBPE_F_DIRTY_OPT_HEADER;
+
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libpe/pe_dos.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,119 @@
+/*-
+ * Copyright (c) 2015 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: pe_dos.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+PE_DosHdr *
+pe_msdos_header(PE *pe)
+{
+
+	if (pe == NULL) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	if (pe->pe_dh == NULL) {
+		errno = ENOENT;
+		return (NULL);
+	}
+
+	return (pe->pe_dh);
+}
+
+char *
+pe_msdos_stub(PE *pe, size_t *len)
+{
+
+	if (pe == NULL || len == NULL) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	if (pe->pe_stub_ex > 0 &&
+	    (pe->pe_flags & LIBPE_F_LOAD_DOS_STUB) == 0) {
+		assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0);
+		(void) libpe_read_msdos_stub(pe);
+	}
+
+	*len = sizeof(PE_DosHdr) + pe->pe_stub_ex;
+
+	return (pe->pe_stub);
+}
+
+int
+ps_update_msdos_header(PE *pe, PE_DosHdr *dh)
+{
+
+	if (pe == NULL || dh == NULL) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) {
+		errno = EACCES;
+		return (-1);
+	}
+
+	if (pe->pe_dh == NULL) {
+		if ((pe->pe_dh = malloc(sizeof(PE_DosHdr))) == NULL) {
+			errno = ENOMEM;
+			return (-1);
+		}
+	}
+
+	*pe->pe_dh = *dh;
+
+	pe->pe_flags |= LIBPE_F_DIRTY_DOS_HEADER;
+
+	return (0);
+}
+
+int
+ps_update_msdos_stub(PE *pe, char *dos_stub, size_t sz)
+{
+
+	if (pe == NULL || dos_stub == NULL || sz == 0) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) {
+		errno = EACCES;
+		return (-1);
+	}
+
+	pe->pe_stub_app = dos_stub;
+	pe->pe_stub_app_sz = sz;
+
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libpe/pe_flag.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,187 @@
+/*-
+ * Copyright (c) 2016 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: pe_flag.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+int
+pe_flag(PE *pe, PE_Cmd c, unsigned int flags)
+{
+
+	if (pe == NULL || (c != PE_C_SET && c != PE_C_CLR)) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	if ((flags & ~(PE_F_STRIP_DOS_STUB | PE_F_STRIP_RICH_HEADER |
+	    PE_F_STRIP_SYMTAB | PE_F_STRIP_DEBUG)) != 0) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	if (c == PE_C_SET)
+		pe->pe_flags |= flags;
+	else
+		pe->pe_flags &= ~flags;
+
+	return (0);
+}
+
+int
+pe_flag_dos_header(PE *pe, PE_Cmd c, unsigned int flags)
+{
+
+	if (pe == NULL || (c != PE_C_SET && c != PE_C_CLR) ||
+	    (flags & ~PE_F_DIRTY) != 0) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	if (c == PE_C_SET)
+		pe->pe_flags |= LIBPE_F_DIRTY_DOS_HEADER;
+	else
+		pe->pe_flags &= ~LIBPE_F_DIRTY_DOS_HEADER;
+
+	return (0);
+}
+
+int
+pe_flag_coff_header(PE *pe, PE_Cmd c, unsigned int flags)
+{
+
+	if (pe == NULL || (c != PE_C_SET && c != PE_C_CLR) ||
+	    (flags & ~PE_F_DIRTY) != 0) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	if (c == PE_C_SET)
+		pe->pe_flags |= LIBPE_F_DIRTY_COFF_HEADER;
+	else
+		pe->pe_flags &= ~LIBPE_F_DIRTY_COFF_HEADER;
+
+	return (0);
+}
+
+int
+pe_flag_opt_header(PE *pe, PE_Cmd c, unsigned int flags)
+{
+
+	if (pe == NULL || (c != PE_C_SET && c != PE_C_CLR) ||
+	    (flags & ~PE_F_DIRTY) != 0) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	if (c == PE_C_SET)
+		pe->pe_flags |= LIBPE_F_DIRTY_OPT_HEADER;
+	else
+		pe->pe_flags &= ~LIBPE_F_DIRTY_OPT_HEADER;
+
+	return (0);
+}
+
+int
+pe_flag_data_dir(PE *pe, PE_Cmd c, unsigned int flags)
+{
+
+	if (pe == NULL || (c != PE_C_SET && c != PE_C_CLR) ||
+	    (flags & ~PE_F_DIRTY) != 0) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	if (c == PE_C_SET)
+		pe->pe_flags |= LIBPE_F_DIRTY_OPT_HEADER;
+	else
+		pe->pe_flags &= ~LIBPE_F_DIRTY_OPT_HEADER;
+
+	return (0);
+}
+
+int
+pe_flag_scn(PE_Scn *ps, PE_Cmd c, unsigned int flags)
+{
+
+	if (ps == NULL || (c != PE_C_SET && c != PE_C_CLR) ||
+	    (flags & ~(PE_F_DIRTY | PE_F_STRIP_SECTION)) == 0) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	if (c == PE_C_SET)
+		ps->ps_flags |= flags;
+	else
+		ps->ps_flags &= ~flags;
+	
+	return (0);
+}
+
+int
+pe_flag_section_header(PE_Scn *ps, PE_Cmd c, unsigned int flags)
+{
+	PE *pe;
+
+	if (ps == NULL || (c != PE_C_SET && c != PE_C_CLR) ||
+	    (flags & ~PE_F_DIRTY) != 0) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	pe = ps->ps_pe;
+
+	/* The library doesn't support per section header dirty flag. */
+	if (c == PE_C_SET)
+		pe->pe_flags |= LIBPE_F_DIRTY_SEC_HEADER;
+	else
+		pe->pe_flags &= ~LIBPE_F_DIRTY_SEC_HEADER;
+
+	return (0);
+}
+
+int
+pe_flag_buffer(PE_Buffer *pb, PE_Cmd c, unsigned int flags)
+{
+	PE_SecBuf *sb;
+
+	if (pb == NULL || (c != PE_C_SET && c != PE_C_CLR) ||
+	    (flags & ~PE_F_DIRTY) != 0) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	sb = (PE_SecBuf *) pb;
+
+	if (c == PE_C_SET)
+		sb->sb_flags |= flags;
+	else
+		sb->sb_flags &= ~flags;
+
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libpe/pe_init.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,95 @@
+/*-
+ * Copyright (c) 2015 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/queue.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: pe_init.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+PE *
+pe_init(int fd, PE_Cmd c, PE_Object o)
+{
+	PE *pe;
+
+	if ((pe = calloc(1, sizeof(*pe))) == NULL) {
+		errno = ENOMEM;
+		return (NULL);
+	}
+	pe->pe_fd = fd;
+	pe->pe_cmd = c;
+	pe->pe_obj = o;
+	STAILQ_INIT(&pe->pe_scn);
+
+	switch (c) {
+	case PE_C_READ:
+	case PE_C_RDWR:
+		if (libpe_open_object(pe) < 0)
+			goto init_fail;
+		break;
+
+	case PE_C_WRITE:
+		if (o < PE_O_PE32 || o > PE_O_COFF) {
+			errno = EINVAL;
+			goto init_fail;
+		}
+		break;
+
+	default:
+		errno = EINVAL;
+		goto init_fail;
+	}
+
+	return (pe);
+
+init_fail:
+	pe_finish(pe);
+	return (NULL);
+}
+
+void
+pe_finish(PE *pe)
+{
+
+	if (pe == NULL)
+		return;
+
+	libpe_release_object(pe);
+}
+
+PE_Object
+pe_object(PE *pe)
+{
+
+	if (pe == NULL) {
+		errno = EINVAL;
+		return (PE_O_UNKNOWN);
+	}
+
+	return (pe->pe_obj);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libpe/pe_rich.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 2016 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: pe_rich.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+PE_RichHdr *
+pe_rich_header(PE *pe)
+{
+
+	if (pe == NULL) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	if (pe->pe_rh == NULL && pe->pe_stub_ex > 0 &&
+	    (pe->pe_flags & LIBPE_F_LOAD_DOS_STUB) == 0) {
+		assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0);
+		(void) libpe_read_msdos_stub(pe);
+	}
+
+	if (pe->pe_rh == NULL) {
+		errno = ENOENT;
+		return (NULL);
+	}
+
+	return (pe->pe_rh);
+}
+
+static uint32_t
+rol32(uint32_t n, int c)
+{
+
+	c &= 0x1f;
+
+	return ((n << c) | (n >> (0x20 - c)));
+}
+
+int
+pe_rich_header_validate(PE *pe)
+{
+	PE_RichHdr *rh;
+	uint32_t cksum;
+	char *p;
+	int i, off;
+
+	if (pe_rich_header(pe) == NULL)
+		return (-1);
+
+	assert(pe->pe_rh_start != NULL);
+
+	/*
+	 * Initial value of the checksum is the offset to the begin of
+	 * the Rich header.
+	 */
+	cksum = pe->pe_rh_start - pe->pe_stub;
+
+	/*
+	 * Add the bytes before the Rich header to the checksum, rotated
+	 * left by the offset.
+	 */
+	for (p = pe->pe_stub; p < pe->pe_rh_start; p++) {
+		/* Skip dh_lfanew. */
+		off = p - pe->pe_stub;
+		if (off >= 0x3c && off < 0x40)
+			continue;
+		cksum += rol32((unsigned char) *p, off);
+	}
+
+	/* Add each compid rotated left by its count to the checksum. */
+	rh = pe->pe_rh;
+	for (i = 0; (uint32_t) i < rh->rh_total; i++)
+		cksum += rol32(rh->rh_compid[i], rh->rh_cnt[i]);
+
+	/* Validate the checksum with the XOR mask stored after "Rich". */
+	if (cksum == rh->rh_xor)
+		return (1);
+
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libpe/pe_section.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,213 @@
+/*-
+ * Copyright (c) 2016 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <string.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: pe_section.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+PE_Scn *
+pe_getscn(PE *pe, size_t ndx)
+{
+	PE_Scn *ps;
+
+	if (pe == NULL || ndx < 1 || ndx > 0xFFFFU) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) {
+		if (ps->ps_ndx == ndx)
+			return (ps);
+	}
+
+	errno = ENOENT;
+
+	return (NULL);
+}
+
+size_t
+pe_ndxscn(PE_Scn *ps)
+{
+
+	if (ps == NULL) {
+		errno = EINVAL;
+		return (0);
+	}
+
+	return (ps->ps_ndx);
+}
+
+PE_Scn *
+pe_nextscn(PE *pe, PE_Scn *ps)
+{
+
+	if (pe == NULL) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	if (ps == NULL)
+		ps = STAILQ_FIRST(&pe->pe_scn);
+	else
+		ps = STAILQ_NEXT(ps, ps_next);
+
+	while (ps != NULL) {
+		if (ps->ps_ndx >= 1 && ps->ps_ndx <= 0xFFFFU)
+			return (ps);
+		ps = STAILQ_NEXT(ps, ps_next);
+	}
+
+	return (NULL);
+}
+
+PE_Scn *
+pe_newscn(PE *pe)
+{
+	PE_Scn *ps, *tps, *_tps;
+
+	if (pe == NULL) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) {
+		errno = EACCES;
+		return (NULL);
+	}
+
+	if ((ps = libpe_alloc_scn(pe)) == NULL)
+		return (NULL);
+
+	if (pe->pe_flags & LIBPE_F_BAD_SEC_HEADER) {
+		STAILQ_FOREACH_SAFE(tps, &pe->pe_scn, ps_next, _tps)
+			libpe_release_scn(tps);
+		pe->pe_flags &= ~LIBPE_F_BAD_SEC_HEADER;
+	}
+
+	STAILQ_INSERT_TAIL(&pe->pe_scn, ps, ps_next);
+
+	ps->ps_flags |= PE_F_DIRTY | LIBPE_F_LOAD_SECTION;
+	pe->pe_flags |= LIBPE_F_DIRTY_SEC_HEADER;
+
+	return (ps);
+}
+
+PE_Scn *
+pe_insertscn(PE *pe, size_t ndx)
+{
+	PE_Scn *ps, *a, *b;
+
+	if (pe == NULL || ndx < 1 || ndx > 0xFFFFU) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) {
+		errno = EACCES;
+		return (NULL);
+	}
+
+	if ((ps = libpe_alloc_scn(pe)) == NULL)
+		return (NULL);
+
+	if (pe->pe_flags & LIBPE_F_BAD_SEC_HEADER) {
+		STAILQ_FOREACH_SAFE(a, &pe->pe_scn, ps_next, b)
+			libpe_release_scn(a);
+		pe->pe_flags &= ~LIBPE_F_BAD_SEC_HEADER;
+	}
+
+	b = NULL;
+	STAILQ_FOREACH(a, &pe->pe_scn, ps_next) {
+		if (a->ps_ndx & 0xFFFF0000U)
+			continue;
+		if (a->ps_ndx == ndx)
+			break;
+		b = a;
+	}
+
+	if (a == NULL) {
+		STAILQ_INSERT_TAIL(&pe->pe_scn, ps, ps_next);
+		if (b == NULL)
+			ps->ps_ndx = 1;
+		else
+			ps->ps_ndx = b->ps_ndx + 1;
+	} else if (b == NULL) {
+		STAILQ_INSERT_HEAD(&pe->pe_scn, ps, ps_next);
+		ps->ps_ndx = 1;
+	} else {
+		STAILQ_INSERT_AFTER(&pe->pe_scn, b, ps, ps_next);
+		ps->ps_ndx = ndx;
+	}
+
+	a = ps;
+	while ((a = STAILQ_NEXT(a, ps_next)) != NULL) {
+		if ((a->ps_ndx & 0xFFFF0000U) == 0)
+			a->ps_ndx++;
+	}
+
+	ps->ps_flags |= PE_F_DIRTY | LIBPE_F_LOAD_SECTION;
+	pe->pe_flags |= LIBPE_F_DIRTY_SEC_HEADER;
+
+	return (ps);
+}
+
+PE_SecHdr *
+pe_section_header(PE_Scn *ps)
+{
+
+	if (ps == NULL) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	return (&ps->ps_sh);
+}
+
+int
+pe_update_section_header(PE_Scn *ps, PE_SecHdr *sh)
+{
+	PE *pe;
+
+	if (ps == NULL || sh == NULL) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	pe = ps->ps_pe;
+
+	if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) {
+		errno = EACCES;
+		return (-1);
+	}
+
+	ps->ps_sh = *sh;
+	pe->pe_flags |= LIBPE_F_DIRTY_SEC_HEADER;
+
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libpe/pe_symtab.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,86 @@
+/*-
+ * Copyright (c) 2016 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: pe_symtab.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+int
+pe_update_symtab(PE *pe, char *symtab, size_t sz, unsigned int nsym)
+{
+	PE_Scn *ps;
+	PE_SecBuf *sb;
+	PE_SecHdr *sh;
+
+	if (pe == NULL || symtab == NULL || sz == 0) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) {
+		errno = EACCES;
+		return (-1);
+	}
+
+	/* Remove the old symbol table. */
+	STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) {
+		if (ps->ps_ndx == 0xFFFFFFFFU)
+			libpe_release_scn(ps);
+	}
+
+	/*
+	 * Insert the new symbol table.
+	 */
+
+	if ((ps = libpe_alloc_scn(pe)) == NULL)
+		return (-1);
+
+	STAILQ_INSERT_TAIL(&pe->pe_scn, ps, ps_next);
+	ps->ps_ndx = 0xFFFFFFFFU;
+	ps->ps_flags |= PE_F_DIRTY;
+
+	/*
+	 * Set the symbol table section offset to the maximum to make sure
+	 * that it will be placed in the end of the file during section
+	 * layout.
+	 */
+	sh = &ps->ps_sh;
+	sh->sh_rawptr = 0xFFFFFFFFU;
+	sh->sh_rawsize = sz;
+
+	/* Allocate the buffer. */
+	if ((sb = libpe_alloc_buffer(ps, 0)) == NULL)
+		return (-1);
+	sb->sb_flags |= PE_F_DIRTY;
+	sb->sb_pb.pb_size = sz;
+	sb->sb_pb.pb_buf = symtab;
+
+	pe->pe_nsym = nsym;
+
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/libpe/pe_update.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,86 @@
+/*-
+ * Copyright (c) 2016 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: pe_update.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+off_t
+pe_update(PE *pe)
+{
+	off_t off;
+
+	if (pe == NULL) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) {
+		errno = EACCES;
+		return (-1);
+	}
+
+	if (pe->pe_cmd == PE_C_RDWR || (pe->pe_cmd == PE_C_WRITE &&
+		(pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0)) {
+		if (lseek(pe->pe_fd, 0, SEEK_SET) < 0) {
+			errno = EIO;
+			return (-1);
+		}
+	}
+
+	off = 0;
+
+	if (pe->pe_obj == PE_O_PE32 || pe->pe_obj == PE_O_PE32P) {
+		if ((off = libpe_write_msdos_stub(pe, off)) < 0)
+			return (-1);
+
+		if ((off = libpe_write_pe_header(pe, off)) < 0)
+			return (-1);
+	}
+
+	if (libpe_resync_sections(pe, off) < 0)
+		return (-1);
+
+	if ((off = libpe_write_coff_header(pe, off)) < 0)
+		return (-1);
+
+	if ((off = libpe_write_section_headers(pe, off)) < 0)
+		return (-1);
+
+	if ((off = libpe_write_sections(pe, off)) < 0)
+		return (-1);
+
+	if (ftruncate(pe->pe_fd, off) < 0) {
+		errno = EIO;
+		return (-1);
+	}
+
+	return (off);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/nm/Makefile	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,13 @@
+
+# $Id: Makefile 2076 2011-10-27 03:50:33Z jkoshy $
+
+TOP=	..
+
+PROG=	nm
+SRCS=	nm.c
+
+WARNS?=	6
+
+LDADD=	-ldwarf -lelftc -lelf
+
+.include "${TOP}/mk/elftoolchain.prog.mk"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/nm/nm.1	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,340 @@
+.\" Copyright (c) 2007 Hyogeol Lee <hyogeollee@gmail.com>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer
+.\"    in this position and unchanged.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $Id: nm.1 3573 2017-09-14 02:06:31Z emaste $
+.\"
+.Dd September 13, 2017
+.Os
+.Dt NM 1
+.Sh NAME
+.Nm nm
+.Nd display symbolic information in object files
+.Sh SYNOPSIS
+.Nm
+.Op Fl -debug-syms
+.Op Fl -defined-only
+.Op Fl -demangle Ns Op = Ns style
+.Op Fl -dynamic
+.Op Fl -extern-only
+.Op Fl -help
+.Op Fl -line-numbers
+.Op Fl -no-demangle
+.Op Fl -no-sort
+.Op Fl -numeric-sort
+.Op Fl -print-armap
+.Op Fl -print-file-name
+.Op Fl -print-size
+.Op Fl -radix= Ns Ar format
+.Op Fl -reverse-sort
+.Op Fl -size-sort
+.Op Fl -undefined-only
+.Op Fl -version
+.Op Fl A
+.Op Fl B
+.Op Fl C Op Ar style
+.Op Fl D
+.Op Fl P
+.Op Fl V
+.Op Fl a
+.Op Fl e
+.Op Fl g
+.Op Fl h
+.Op Fl l
+.Op Fl n
+.Op Fl o
+.Op Fl p
+.Op Fl r
+.Op Fl S
+.Op Fl s
+.Op Fl t Ar format
+.Op Fl u
+.Op Fl x
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility displays symbolic information in the object files,
+executables, and object library files named by its arguments.
+Lack of symbolic information in an otherwise valid input
+file, is not considered to be an error.
+If no files are specified on the command line,
+.Nm
+will attempt to read
+.Pa a.out .
+.Pp
+The
+.Nm
+utility recognizes the following options:
+.Bl -tag -width ".Fl d Ar argument"
+.It Fl -debug-syms
+Display all symbols, including debugger-only symbols.
+.It Fl -defined-only
+Display only defined symbols.
+.It Fl -demangle Ns Op = Ns Ar style
+Decode (demangle) low-level symbol names into human-readable names.
+Supported values for argument
+.Ar style
+are
+.Sq auto ,
+.Sq gnu-v2 ,
+.Sq gnu-v3
+and
+.Sq arm.
+If argument
+.Ar style
+is not specified, it is taken to be
+.Sq auto .
+.It Fl -dynamic
+Only display dynamic symbols.
+This option is only meaningful for shared libraries.
+.It Fl -extern-only
+Only display information about global (external) symbols.
+.It Fl -help
+Display a help message and exit.
+.It Fl -format Ns = Ns Ar format
+Display output in the format specified by argument
+.Ar format .
+Supported values for the format argument are
+.Sq bsd ,
+.Sq sysv ,
+and
+.Sq posix .
+The default output format is
+.Sq bsd .
+.It Fl -line-numbers
+Display the filename and line number associated a symbol using
+any debugging information present in the input file.
+For defined symbols, look up the line number associated with
+the address of the symbol.
+For undefined symbols, look up the line number associated with
+a relocation entry that refers to the symbol.
+If line number information can be determined, it is displayed after
+other symbol information.
+.It Fl -no-demangle
+Do not demangle symbol names (default).
+.It Fl -no-sort
+Do not sort symbols.
+.It Fl -numeric-sort
+Sort symbols numerically by address instead of alphabetically by name.
+.It Fl -print-armap
+For
+.Xr ar 1
+archives, include the index of the archive's members.
+.It Fl -print-file-name
+Write the full pathname or library name of an object on each line,
+before the rest of the information for a symbol.
+If this option is not specified,
+.Nm
+will only identify an input file once, before its symbols are
+listed.
+.It Fl -print-size
+Print the size of each symbol instead of its value.
+.It Fl -radix Ns = Ns Ar radix
+Print numeric values using the specified radix.
+Supported values for argument
+.Ar radix
+are
+.Sq d
+for decimal,
+.Sq o
+for octal, and
+.Sq x
+for hexadecimal.
+.It Fl -reverse-sort
+Reverse the order of the sort.
+.It Fl -size-sort
+Sort symbols by size instead of alphabetically by name.
+.It Fl -undefined-only
+Display only undefined symbols.
+.It Fl -version
+Display the version identifier for
+.Nm
+and exit.
+.It Fl A
+Equivalent to specifying option
+.Fl -print-file-name .
+.It Fl B
+Equivalent to specifying option
+.Fl -format= Ns Ar bsd .
+.It Fl C Op Ar style
+Equivalent to specifying option
+.Fl -demangle Ns Op = Ns Ar style .
+.It Fl D
+Equivalent to specifying option
+.Fl -dynamic .
+.It Fl F Ar format
+Equivalent to specifying option
+.Fl -format Ns = Ns Ar format .
+.It Fl P
+Equivalent to specifying option
+.Fl -format Ns = Ns Ar posix .
+.It Fl S
+Equivalent to specifying option
+.Fl -print-size .
+.It Fl V
+Equivalent to specifying option
+.Fl -version .
+.It Fl a
+Equivalent to specifying option
+.Fl -debug-syms .
+.It Fl e
+Only display information for global and static symbols.
+.It Fl f
+Produce full output (default).
+.It Fl g
+Equivalent to specifying option
+.Fl -extern-only .
+.It Fl h
+Equivalent to specifying option
+.Fl -help .
+.It Fl l
+Equivalent to specifying option
+.Fl -line-numbers .
+.It Fl n
+Equivalent to specifying option
+.Fl -numeric-sort .
+.It Fl o
+If POSIX output was specified using the
+.Fl F Ar posix
+or
+.Fl P
+options, this option is equivalent to specifying
+.Fl -radix Ns = Ns Sq Ar o .
+If POSIX output was not specified, this option
+acts as a synonym for the
+.Fl -print-file-name
+option.
+.It Fl p
+Equivalent to specifying option
+.Fl -no-sort .
+.It Fl v
+Equivalent to option
+.Fl n .
+.It Fl r
+Equivalent to specifying option
+.Fl -reverse-sort
+.It Fl s
+Equivalent to specifying option
+.Fl -print-armap .
+.It Fl t Ar radix
+Equivalent to specifying option
+.Fl -radix= Ns Ar radix .
+.It Fl u
+Equivalent to specifying option
+.Fl -undefined-only .
+.It Fl x
+Write numeric values in hexadecimal (equivalent to -t x).
+.El
+.Sh OUTPUT FORMAT
+.Pp
+The
+.Nm
+utility can present its information in a number of formats, numeric
+radices and sort orders.
+By default
+.Nm
+uses BSD style output, a hexadecimal radix, without output sorted
+alphabetically by name and without demangling of names.
+.Pp
+For each symbol listed,
+.Nm
+presents the following information:
+.Bl -bullet -compact
+.It
+The library or object name, if options
+.Fl A
+or
+.Fl -print-file-name
+were specified.
+.It
+The symbol name.
+.It
+The type of the symbol denoted by a single character as below:
+.Bl -tag -compact -width indent
+.It A
+A global, absolute symbol.
+.It B
+A global
+.Dq bss
+(uninitialized data) symbol.
+.It C
+A
+.Dq common
+symbol, representing uninitialized data.
+.It D
+A global symbol naming initialized data.
+.It N
+A debugger symbol.
+.It R
+A read-only data symbol.
+.It T
+A global text symbol.
+.It U
+An undefined symbol.
+.It V
+A weak object.
+.It W
+A weak reference.
+.It a
+A local absolute symbol.
+.It b
+A local
+.Dq bss
+(uninitialized data) symbol.
+.It d
+A local data symbol.
+.It r
+A local read-only data symbol.
+.It t
+A local text symbol.
+.It v
+A weak object that is undefined.
+.It w
+A weak symbol that is undefined.
+.It ?
+None of the above.
+.El
+.It
+The value of the symbol.
+.It
+The size of the symbol if applicable.
+.It
+Line number information, if available and if options
+.Fl l
+or
+.Fl -line-numbers
+were specified.
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh SEE ALSO
+.Xr ar 1 ,
+.Xr objdump 1 ,
+.Xr ranlib 1 ,
+.Xr elf 3
+.Sh AUTHORS
+The
+.Nm
+utility and this manual page were written by
+.An Hyogeol Lee Aq Mt hyogeollee@gmail.com .
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/nm/nm.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,2123 @@
+/*-
+ * Copyright (c) 2007 Hyogeol Lee <hyogeollee@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ar.h>
+#include <assert.h>
+#include <ctype.h>
+#include <dwarf.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <getopt.h>
+#include <inttypes.h>
+#include <libdwarf.h>
+#include <libelftc.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+
+#include "_elftc.h"
+
+ELFTC_VCSID("$Id: nm.c 3504 2016-12-17 15:33:16Z kaiwang27 $");
+
+/* symbol information list */
+STAILQ_HEAD(sym_head, sym_entry);
+
+struct sym_entry {
+	char		*name;
+	GElf_Sym	*sym;
+	STAILQ_ENTRY(sym_entry) sym_entries;
+};
+
+typedef int (*fn_sort)(const void *, const void *);
+typedef void (*fn_elem_print)(char, const char *, const GElf_Sym *, const char *);
+typedef void (*fn_sym_print)(const GElf_Sym *);
+typedef int (*fn_filter)(char, const GElf_Sym *, const char *);
+
+/* output filter list */
+static SLIST_HEAD(filter_head, filter_entry) nm_out_filter =
+    SLIST_HEAD_INITIALIZER(nm_out_filter);
+
+struct filter_entry {
+	fn_filter	fn;
+	SLIST_ENTRY(filter_entry) filter_entries;
+};
+
+struct sym_print_data {
+	struct sym_head	*headp;
+	size_t		sh_num, list_num;
+	const char	*t_table, **s_table, *filename, *objname;
+};
+
+struct nm_prog_info {
+	const char	*name;
+	const char	*def_filename;
+};
+
+/* List for line number information. */
+struct line_info_entry {
+	uint64_t	addr;	/* address */
+	uint64_t	line;	/* line number */
+	char		*file;	/* file name with path */
+	SLIST_ENTRY(line_info_entry) entries;
+};
+SLIST_HEAD(line_info_head, line_info_entry);
+
+/* List for function line number information. */
+struct func_info_entry {
+	char		*name;	/* function name */
+	char		*file;	/* file name with path */
+	uint64_t	lowpc;	/* low address */
+	uint64_t	highpc;	/* high address */
+	uint64_t	line;	/* line number */
+	SLIST_ENTRY(func_info_entry) entries;
+};
+SLIST_HEAD(func_info_head, func_info_entry);
+
+/* List for variable line number information. */
+struct var_info_entry {
+	char		*name;	/* variable name */
+	char		*file;	/* file name with path */
+	uint64_t	addr;	/* address */
+	uint64_t	line;	/* line number */
+	SLIST_ENTRY(var_info_entry) entries;
+};
+SLIST_HEAD(var_info_head, var_info_entry);
+
+/* output numric type */
+enum radix {
+	RADIX_OCT,
+	RADIX_HEX,
+	RADIX_DEC
+};
+
+/* output symbol type, PRINT_SYM_DYN for dynamic symbol only */
+enum print_symbol {
+	PRINT_SYM_SYM,
+	PRINT_SYM_DYN
+};
+
+/* output name type */
+enum print_name {
+	PRINT_NAME_NONE,
+	PRINT_NAME_FULL,
+	PRINT_NAME_MULTI
+};
+
+struct nm_prog_options {
+	enum print_symbol	print_symbol;
+	enum print_name		print_name;
+	enum radix		t;
+	int			demangle_type;
+	bool			print_debug;
+	bool			print_armap;
+	int			print_size;
+	bool			debug_line;
+	int			def_only;
+	bool			undef_only;
+	int			sort_size;
+	bool			sort_reverse;
+	int			no_demangle;
+
+	/*
+	 * function pointer to sort symbol list.
+	 * possible function - cmp_name, cmp_none, cmp_size, cmp_value
+	 */
+	fn_sort			sort_fn;
+
+	/*
+	 * function pointer to print symbol elem.
+	 * possible function - sym_elem_print_all
+	 *		       sym_elem_print_all_portable
+	 *		       sym_elem_print_all_sysv
+	 */
+	fn_elem_print		elem_print_fn;
+
+	fn_sym_print		value_print_fn;
+	fn_sym_print		size_print_fn;
+};
+
+#define	CHECK_SYM_PRINT_DATA(p)	(p->headp == NULL || p->sh_num == 0 ||	      \
+p->t_table == NULL || p->s_table == NULL || p->filename == NULL)
+#define	IS_SYM_TYPE(t)		((t) == '?' || isalpha((t)) != 0)
+#define	IS_UNDEF_SYM_TYPE(t)	((t) == 'U' || (t) == 'v' || (t) == 'w')
+#define	UNUSED(p)		((void)p)
+
+static int		cmp_name(const void *, const void *);
+static int		cmp_none(const void *, const void *);
+static int		cmp_size(const void *, const void *);
+static int		cmp_value(const void *, const void *);
+static void		filter_dest(void);
+static int		filter_insert(fn_filter);
+static void		get_opt(int, char **);
+static int		get_sym(Elf *, struct sym_head *, int, size_t, size_t,
+			    const char *, const char **, int);
+static const char *	get_sym_name(Elf *, const GElf_Sym *, size_t,
+			    const char **, int);
+static char		get_sym_type(const GElf_Sym *, const char *);
+static void		global_dest(void);
+static void		global_init(void);
+static bool		is_sec_data(GElf_Shdr *);
+static bool		is_sec_debug(const char *);
+static bool		is_sec_nobits(GElf_Shdr *);
+static bool		is_sec_readonly(GElf_Shdr *);
+static bool		is_sec_text(GElf_Shdr *);
+static void		print_ar_index(int, Elf *);
+static void		print_header(const char *, const char *);
+static void		print_version(void);
+static int		read_elf(Elf *, const char *, Elf_Kind);
+static int		read_object(const char *);
+static int		read_files(int, char **);
+static void		set_opt_value_print_fn(enum radix);
+static int		sym_elem_def(char, const GElf_Sym *, const char *);
+static int		sym_elem_global(char, const GElf_Sym *, const char *);
+static int		sym_elem_global_static(char, const GElf_Sym *,
+			    const char *);
+static int		sym_elem_nondebug(char, const GElf_Sym *, const char *);
+static int		sym_elem_nonzero_size(char, const GElf_Sym *,
+			    const char *);
+static void		sym_elem_print_all(char, const char *,
+			    const GElf_Sym *, const char *);
+static void		sym_elem_print_all_portable(char, const char *,
+			    const GElf_Sym *, const char *);
+static void		sym_elem_print_all_sysv(char, const char *,
+			    const GElf_Sym *, const char *);
+static int		sym_elem_undef(char, const GElf_Sym *, const char *);
+static void		sym_list_dest(struct sym_head *);
+static int		sym_list_insert(struct sym_head *, const char *,
+			    const GElf_Sym *);
+static void		sym_list_print(struct sym_print_data *,
+			    struct func_info_head *, struct var_info_head *,
+			    struct line_info_head *);
+static void		sym_list_print_each(struct sym_entry *,
+			    struct sym_print_data *, struct func_info_head *,
+			    struct var_info_head *, struct line_info_head *);
+static struct sym_entry	*sym_list_sort(struct sym_print_data *);
+static void		sym_size_oct_print(const GElf_Sym *);
+static void		sym_size_hex_print(const GElf_Sym *);
+static void		sym_size_dec_print(const GElf_Sym *);
+static void		sym_value_oct_print(const GElf_Sym *);
+static void		sym_value_hex_print(const GElf_Sym *);
+static void		sym_value_dec_print(const GElf_Sym *);
+static void		usage(int);
+
+static struct nm_prog_info	nm_info;
+static struct nm_prog_options	nm_opts;
+static int			nm_elfclass;
+
+/*
+ * Point to current sym_print_data to use portable qsort function.
+ *  (e.g. There is no qsort_r function in NetBSD.)
+ *
+ * Using in sym_list_sort.
+ */
+static struct sym_print_data	*nm_print_data;
+
+static const struct option nm_longopts[] = {
+	{ "debug-syms",		no_argument,		NULL,		'a' },
+	{ "defined-only",	no_argument,		&nm_opts.def_only, 1},
+	{ "demangle",		optional_argument,	NULL,		'C' },
+	{ "dynamic",		no_argument,		NULL,		'D' },
+	{ "extern-only",	no_argument,		NULL,		'g' },
+	{ "format",		required_argument,	NULL,		'F' },
+	{ "help",		no_argument,		NULL,		'h' },
+	{ "line-numbers",	no_argument,		NULL,		'l' },
+	{ "no-demangle",	no_argument,		&nm_opts.no_demangle,
+	  1},
+	{ "no-sort",		no_argument,		NULL,		'p' },
+	{ "numeric-sort",	no_argument,		NULL,		'v' },
+	{ "print-armap",	no_argument,		NULL,		's' },
+	{ "print-file-name",	no_argument,		NULL,		'A' },
+	{ "print-size",		no_argument,		NULL,		'S' },
+	{ "radix",		required_argument,	NULL,		't' },
+	{ "reverse-sort",	no_argument,		NULL,		'r' },
+	{ "size-sort",		no_argument,		&nm_opts.sort_size, 1},
+	{ "undefined-only",	no_argument,		NULL,		'u' },
+	{ "version",		no_argument,		NULL,		'V' },
+	{ NULL,			0,			NULL,		0   }
+};
+
+#if defined(ELFTC_NEED_BYTEORDER_EXTENSIONS)
+static __inline uint32_t
+be32dec(const void *pp)
+{
+	unsigned char const *p = (unsigned char const *)pp;
+
+	return ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
+}
+
+static __inline uint32_t
+le32dec(const void *pp)
+{
+	unsigned char const *p = (unsigned char const *)pp;
+
+	return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]);
+}
+
+static __inline uint64_t
+be64dec(const void *pp)
+{
+	unsigned char const *p = (unsigned char const *)pp;
+
+	return (((uint64_t)be32dec(p) << 32) | be32dec(p + 4));
+}
+
+static __inline uint64_t
+le64dec(const void *pp)
+{
+	unsigned char const *p = (unsigned char const *)pp;
+
+	return (((uint64_t)le32dec(p + 4) << 32) | le32dec(p));
+}
+#endif
+
+static int
+cmp_name(const void *l, const void *r)
+{
+
+	assert(l != NULL);
+	assert(r != NULL);
+	assert(((const struct sym_entry *)l)->name != NULL);
+	assert(((const struct sym_entry *)r)->name != NULL);
+
+	return (strcmp(((const struct sym_entry *)l)->name,
+	    ((const struct sym_entry *)r)->name));
+}
+
+static int
+cmp_none(const void *l, const void *r)
+{
+
+	UNUSED(l);
+	UNUSED(r);
+
+	return (0);
+}
+
+/* Size comparison. If l and r have same size, compare their name. */
+static int
+cmp_size(const void *lp, const void *rp)
+{
+	const struct sym_entry *l, *r;
+
+	l = lp;
+	r = rp;
+
+	assert(l != NULL);
+	assert(l->name != NULL);
+	assert(l->sym != NULL);
+	assert(r != NULL);
+	assert(r->name != NULL);
+	assert(r->sym != NULL);
+
+	if (l->sym->st_size == r->sym->st_size)
+		return (strcmp(l->name, r->name));
+
+	return (l->sym->st_size - r->sym->st_size);
+}
+
+/* Value comparison. Undefined symbols come first. */
+static int
+cmp_value(const void *lp, const void *rp)
+{
+	const struct sym_entry *l, *r;
+	const char *ttable;
+	int l_is_undef, r_is_undef;
+
+	l = lp;
+	r = rp;
+
+	assert(nm_print_data != NULL);
+	ttable = nm_print_data->t_table;
+
+	assert(l != NULL);
+	assert(l->name != NULL);
+	assert(l->sym != NULL);
+	assert(r != NULL);
+	assert(r->name != NULL);
+	assert(r->sym != NULL);
+	assert(ttable != NULL);
+
+	l_is_undef = IS_UNDEF_SYM_TYPE(get_sym_type(l->sym, ttable)) ? 1 : 0;
+	r_is_undef = IS_UNDEF_SYM_TYPE(get_sym_type(r->sym, ttable)) ? 1 : 0;
+
+	assert(l_is_undef + r_is_undef >= 0);
+	assert(l_is_undef + r_is_undef <= 2);
+
+	switch (l_is_undef + r_is_undef) {
+	case 0:
+		/* Both defined */
+		if (l->sym->st_value == r->sym->st_value)
+			return (strcmp(l->name, r->name));
+		return (l->sym->st_value > r->sym->st_value ? 1 : -1);
+	case 1:
+		/* One undefined */
+		return (l_is_undef == 0 ? 1 : -1);
+	case 2:
+		/* Both undefined */
+		return (strcmp(l->name, r->name));
+	}
+	/* NOTREACHED */
+
+	return (l->sym->st_value - r->sym->st_value);
+}
+
+static void
+filter_dest(void)
+{
+	struct filter_entry *e;
+
+	while (!SLIST_EMPTY(&nm_out_filter)) {
+		e = SLIST_FIRST(&nm_out_filter);
+		SLIST_REMOVE_HEAD(&nm_out_filter, filter_entries);
+		free(e);
+	}
+}
+
+static int
+filter_insert(fn_filter filter_fn)
+{
+	struct filter_entry *e;
+
+	assert(filter_fn != NULL);
+
+	if ((e = malloc(sizeof(struct filter_entry))) == NULL) {
+		warn("malloc");
+		return (0);
+	}
+	e->fn = filter_fn;
+	SLIST_INSERT_HEAD(&nm_out_filter, e, filter_entries);
+
+	return (1);
+}
+
+static int
+parse_demangle_option(const char *opt)
+{
+
+	if (opt == NULL)
+		return (ELFTC_DEM_UNKNOWN);
+	else if (!strncasecmp(opt, "gnu-v2", 6))
+		return (ELFTC_DEM_GNU2);
+	else if (!strncasecmp(opt, "gnu-v3", 6))
+		return (ELFTC_DEM_GNU3);
+	else if (!strncasecmp(opt, "arm", 3))
+		return (ELFTC_DEM_ARM);
+	else
+		errx(EXIT_FAILURE, "unknown demangling style '%s'", opt);
+
+	/* NOTREACHED */
+	return (0);
+}
+
+static void
+get_opt(int argc, char **argv)
+{
+	int ch;
+	bool is_posix, oflag;
+
+	if (argc <= 0 || argv == NULL)
+		return;
+
+	oflag = is_posix = false;
+	nm_opts.t = RADIX_HEX;
+	while ((ch = getopt_long(argc, argv, "ABCDF:PSVaefghlnoprst:uvx",
+		    nm_longopts, NULL)) != -1) {
+		switch (ch) {
+		case 'A':
+			nm_opts.print_name = PRINT_NAME_FULL;
+			break;
+		case 'B':
+			nm_opts.elem_print_fn = &sym_elem_print_all;
+			break;
+		case 'C':
+			nm_opts.demangle_type = parse_demangle_option(optarg);
+			break;
+		case 'D':
+			nm_opts.print_symbol = PRINT_SYM_DYN;
+			break;
+		case 'F':
+			/* sysv, bsd, posix */
+			switch (optarg[0]) {
+			case 'B':
+			case 'b':
+				nm_opts.elem_print_fn = &sym_elem_print_all;
+				break;
+			case 'P':
+			case 'p':
+				is_posix = true;
+				nm_opts.elem_print_fn =
+				    &sym_elem_print_all_portable;
+				break;
+			case 'S':
+			case 's':
+				nm_opts.elem_print_fn =
+				    &sym_elem_print_all_sysv;
+				break;
+			default:
+				warnx("%s: Invalid format", optarg);
+				usage(1);
+			}
+
+			break;
+		case 'P':
+			is_posix = true;
+			nm_opts.elem_print_fn = &sym_elem_print_all_portable;
+			break;
+		case 'S':
+			nm_opts.print_size = 1;
+			break;
+		case 'V':
+			print_version();
+			/* NOTREACHED */
+		case 'a':
+			nm_opts.print_debug = true;
+			break;
+		case 'e':
+			filter_insert(sym_elem_global_static);
+			break;
+		case 'f':
+			break;
+		case 'g':
+			filter_insert(sym_elem_global);
+			break;
+		case 'h':
+			usage(0);
+			break;
+		case 'l':
+			nm_opts.debug_line = true;
+			break;
+		case 'n':
+		case 'v':
+			nm_opts.sort_fn = &cmp_value;
+			break;
+		case 'o':
+			oflag = true;
+			break;
+		case 'p':
+			nm_opts.sort_fn = &cmp_none;
+			break;
+		case 'r':
+			nm_opts.sort_reverse = true;
+			break;
+		case 's':
+			nm_opts.print_armap = true;
+			break;
+		case 't':
+			/* t require always argument to getopt_long */
+			switch (optarg[0]) {
+			case 'd':
+				nm_opts.t = RADIX_DEC;
+				break;
+			case 'o':
+				nm_opts.t = RADIX_OCT;
+				break;
+			case 'x':
+				nm_opts.t = RADIX_HEX;
+				break;
+			default:
+				warnx("%s: Invalid radix", optarg);
+				usage(1);
+			}
+			break;
+		case 'u':
+			filter_insert(sym_elem_undef);
+			nm_opts.undef_only = true;
+			break;
+		/* case 'v': see case 'n' above. */
+		case 'x':
+			nm_opts.t = RADIX_HEX;
+			break;
+		case 0:
+			if (nm_opts.sort_size != 0) {
+				nm_opts.sort_fn = &cmp_size;
+				filter_insert(sym_elem_def);
+				filter_insert(sym_elem_nonzero_size);
+			}
+			if (nm_opts.def_only != 0)
+				filter_insert(sym_elem_def);
+			if (nm_opts.no_demangle != 0)
+				nm_opts.demangle_type = -1;
+			break;
+		default :
+			usage(1);
+		}
+	}
+
+	/*
+	 * In POSIX mode, the '-o' option controls the output radix.
+	 * In non-POSIX mode, the option is a synonym for the '-A' and
+	 * '--print-file-name' options.
+	 */
+	if (oflag) {
+		if (is_posix)
+			nm_opts.t = RADIX_OCT;
+		else
+			nm_opts.print_name = PRINT_NAME_FULL;
+	}
+
+	assert(nm_opts.sort_fn != NULL && "nm_opts.sort_fn is null");
+	assert(nm_opts.elem_print_fn != NULL &&
+	    "nm_opts.elem_print_fn is null");
+	assert(nm_opts.value_print_fn != NULL &&
+	    "nm_opts.value_print_fn is null");
+
+	set_opt_value_print_fn(nm_opts.t);
+
+	if (nm_opts.undef_only == true) {
+		if (nm_opts.sort_fn == &cmp_size)
+			errx(EXIT_FAILURE,
+			    "--size-sort with -u is meaningless");
+		if (nm_opts.def_only != 0)
+			errx(EXIT_FAILURE,
+			    "-u with --defined-only is meaningless");
+	}
+	if (nm_opts.print_debug == false)
+		filter_insert(sym_elem_nondebug);
+	if (nm_opts.sort_reverse == true && nm_opts.sort_fn == cmp_none)
+		nm_opts.sort_reverse = false;
+}
+
+/*
+ * Get symbol information from elf.
+ */
+static int
+get_sym(Elf *elf, struct sym_head *headp, int shnum, size_t dynndx,
+    size_t strndx, const char *type_table, const char **sec_table,
+    int sec_table_size)
+{
+	Elf_Scn *scn;
+	Elf_Data *data;
+	GElf_Shdr shdr;
+	GElf_Sym sym;
+	struct filter_entry *fep;
+	size_t ndx;
+	int rtn;
+	const char *sym_name;
+	char type;
+	bool filter;
+	int i, j;
+
+	assert(elf != NULL);
+	assert(headp != NULL);
+
+	rtn = 0;
+	for (i = 1; i < shnum; i++) {
+		if ((scn = elf_getscn(elf, i)) == NULL) {
+			warnx("elf_getscn failed: %s", elf_errmsg(-1));
+			continue;
+		}
+		if (gelf_getshdr(scn, &shdr) != &shdr) {
+			warnx("gelf_getshdr failed: %s", elf_errmsg(-1));
+			continue;
+		}
+		if (shdr.sh_type == SHT_SYMTAB) {
+			if (nm_opts.print_symbol != PRINT_SYM_SYM)
+				continue;
+		} else if (shdr.sh_type == SHT_DYNSYM) {
+			if (nm_opts.print_symbol != PRINT_SYM_DYN)
+				continue;
+		} else
+			continue;
+
+		ndx = shdr.sh_type == SHT_DYNSYM ? dynndx : strndx;
+
+		data = NULL;
+		while ((data = elf_getdata(scn, data)) != NULL) {
+			j = 1;
+			while (gelf_getsym(data, j++, &sym) != NULL) {
+				sym_name = get_sym_name(elf, &sym, ndx,
+				    sec_table, sec_table_size);
+				filter = false;
+				type = get_sym_type(&sym, type_table);
+				SLIST_FOREACH(fep, &nm_out_filter,
+				    filter_entries) {
+					if (!fep->fn(type, &sym, sym_name)) {
+						filter = true;
+						break;
+					}
+				}
+				if (filter == false) {
+					if (sym_list_insert(headp, sym_name,
+					    &sym) == 0)
+						return (0);
+					rtn++;
+				}
+			}
+		}
+	}
+
+	return (rtn);
+}
+
+static const char *
+get_sym_name(Elf *elf, const GElf_Sym *sym, size_t ndx, const char **sec_table,
+    int sec_table_size)
+{
+	const char *sym_name;
+
+	sym_name = NULL;
+
+	/* Show section name as symbol name for STT_SECTION symbols. */
+	if (GELF_ST_TYPE(sym->st_info) == STT_SECTION) {
+		if (sec_table != NULL && sym->st_shndx < sec_table_size)
+			sym_name = sec_table[sym->st_shndx];
+	} else
+		sym_name = elf_strptr(elf, ndx, sym->st_name);
+
+	if (sym_name == NULL)
+		sym_name = "(null)";
+
+	return (sym_name);
+}
+
+static char
+get_sym_type(const GElf_Sym *sym, const char *type_table)
+{
+	bool is_local;
+
+	if (sym == NULL || type_table == NULL)
+		return ('?');
+
+	is_local = sym->st_info >> 4 == STB_LOCAL;
+
+	if (sym->st_shndx == SHN_ABS) /* absolute */
+		return (is_local ? 'a' : 'A');
+
+	if (sym->st_shndx == SHN_COMMON) /* common */
+		return ('C');
+
+	if ((sym->st_info) >> 4 == STB_WEAK) { /* weak */
+		if ((sym->st_info & 0xf) == STT_OBJECT)
+			return (sym->st_shndx == SHN_UNDEF ? 'v' : 'V');
+
+		return (sym->st_shndx == SHN_UNDEF ? 'w' : 'W');
+	}
+
+	if (sym->st_shndx == SHN_UNDEF) /* undefined */
+		return ('U');
+
+	return (is_local == true && type_table[sym->st_shndx] != 'N' ?
+	    tolower((unsigned char) type_table[sym->st_shndx]) :
+	    type_table[sym->st_shndx]);
+}
+
+static void
+global_dest(void)
+{
+
+	filter_dest();
+}
+
+static void
+global_init(void)
+{
+
+	if (elf_version(EV_CURRENT) == EV_NONE)
+		errx(EXIT_FAILURE, "elf_version error");
+
+	nm_info.name = ELFTC_GETPROGNAME();
+	nm_info.def_filename = "a.out";
+	nm_opts.print_symbol = PRINT_SYM_SYM;
+	nm_opts.print_name = PRINT_NAME_NONE;
+	nm_opts.demangle_type = -1;
+	nm_opts.print_debug = false;
+	nm_opts.print_armap = false;
+	nm_opts.print_size = 0;
+	nm_opts.debug_line = false;
+	nm_opts.def_only = 0;
+	nm_opts.undef_only = false;
+	nm_opts.sort_size = 0;
+	nm_opts.sort_reverse = false;
+	nm_opts.no_demangle = 0;
+	nm_opts.sort_fn = &cmp_name;
+	nm_opts.elem_print_fn = &sym_elem_print_all;
+	nm_opts.value_print_fn = &sym_value_dec_print;
+	nm_opts.size_print_fn = &sym_size_dec_print;
+	SLIST_INIT(&nm_out_filter);
+}
+
+static bool
+is_sec_data(GElf_Shdr *s)
+{
+
+	assert(s != NULL && "shdr is NULL");
+
+	return (((s->sh_flags & SHF_ALLOC) != 0) && s->sh_type != SHT_NOBITS);
+}
+
+static bool
+is_sec_debug(const char *shname)
+{
+	const char *dbg_sec[] = {
+		".debug",
+		".gnu.linkonce.wi.",
+		".line",
+		".rel.debug",
+		".rela.debug",
+		".stab",
+		NULL
+	};
+	const char **p;
+
+	if (shname == NULL)
+		return (false);
+
+	for (p = dbg_sec; *p; p++) {
+		if (!strncmp(shname, *p, strlen(*p)))
+			return (true);
+	}
+
+	return (false);
+}
+
+static bool
+is_sec_nobits(GElf_Shdr *s)
+{
+
+	assert(s != NULL && "shdr is NULL");
+
+	return (s->sh_type == SHT_NOBITS);
+}
+
+static bool
+is_sec_readonly(GElf_Shdr *s)
+{
+
+	assert(s != NULL && "shdr is NULL");
+
+	return ((s->sh_flags & SHF_WRITE) == 0);
+}
+
+static bool
+is_sec_text(GElf_Shdr *s)
+{
+
+	assert(s != NULL && "shdr is NULL");
+
+	return ((s->sh_flags & SHF_EXECINSTR) != 0);
+}
+
+static void
+print_ar_index(int fd, Elf *arf)
+{
+	Elf *elf;
+	Elf_Arhdr *arhdr;
+	Elf_Arsym *arsym;
+	Elf_Cmd cmd;
+	off_t start;
+	size_t arsym_size;
+
+	if (arf == NULL)
+		return;
+
+	if ((arsym = elf_getarsym(arf, &arsym_size)) == NULL)
+		return;
+
+	printf("\nArchive index:\n");
+
+	start = arsym->as_off;
+	cmd = ELF_C_READ;
+	while (arsym_size > 1) {
+		if (elf_rand(arf, arsym->as_off) == arsym->as_off &&
+		    (elf = elf_begin(fd, cmd, arf)) != NULL) {
+			if ((arhdr = elf_getarhdr(elf)) != NULL)
+				printf("%s in %s\n", arsym->as_name,
+				    arhdr->ar_name != NULL ?
+				    arhdr->ar_name : arhdr->ar_rawname);
+			elf_end(elf);
+		}
+		++arsym;
+		--arsym_size;
+	}
+
+	elf_rand(arf, start);
+}
+
+#define	DEMANGLED_BUFFER_SIZE	(8 * 1024)
+#define	PRINT_DEMANGLED_NAME(FORMAT, NAME) do {				\
+	char _demangled[DEMANGLED_BUFFER_SIZE];				\
+	if (nm_opts.demangle_type < 0 ||				\
+	    elftc_demangle((NAME), _demangled, sizeof(_demangled),	\
+		nm_opts.demangle_type) < 0)				\
+		printf((FORMAT), (NAME));				\
+	else								\
+		printf((FORMAT), _demangled);				\
+	} while (0)
+
+static void
+print_header(const char *file, const char *obj)
+{
+
+	if (file == NULL)
+		return;
+
+	if (nm_opts.elem_print_fn == &sym_elem_print_all_sysv) {
+		printf("\n\n%s from %s",
+		    nm_opts.undef_only == false ? "Symbols" :
+		    "Undefined symbols", file);
+		if (obj != NULL)
+			printf("[%s]", obj);
+		printf(":\n\n");
+
+		printf("\
+Name                  Value           Class        Type         Size             Line  Section\n\n");
+	} else {
+		/* archive file without -A option and POSIX */
+		if (nm_opts.print_name != PRINT_NAME_FULL && obj != NULL) {
+			if (nm_opts.elem_print_fn ==
+			    sym_elem_print_all_portable)
+				printf("%s[%s]:\n", file, obj);
+			else if (nm_opts.elem_print_fn == sym_elem_print_all)
+				printf("\n%s:\n", obj);
+			/* multiple files(not archive) without -A option */
+		} else if (nm_opts.print_name == PRINT_NAME_MULTI) {
+			if (nm_opts.elem_print_fn == sym_elem_print_all)
+				printf("\n");
+			printf("%s:\n", file);
+		}
+	}
+}
+
+static void
+print_version(void)
+{
+
+	(void) printf("%s (%s)\n", nm_info.name, elftc_version());
+	exit(0);
+}
+
+static uint64_t
+get_block_value(Dwarf_Debug dbg, Dwarf_Block *block)
+{
+	Elf *elf;
+	GElf_Ehdr eh;
+	Dwarf_Error de;
+
+	if (dwarf_get_elf(dbg, &elf, &de) != DW_DLV_OK) {
+		warnx("dwarf_get_elf failed: %s", dwarf_errmsg(de));
+		return (0);
+	}
+
+	if (gelf_getehdr(elf, &eh) != &eh) {
+		warnx("gelf_getehdr failed: %s", elf_errmsg(-1));
+		return (0);
+	}
+
+	if (block->bl_len == 5) {
+		if (eh.e_ident[EI_DATA] == ELFDATA2LSB)
+			return (le32dec((uint8_t *) block->bl_data + 1));
+		else
+			return (be32dec((uint8_t *) block->bl_data + 1));
+	} else if (block->bl_len == 9) {
+		if (eh.e_ident[EI_DATA] == ELFDATA2LSB)
+			return (le64dec((uint8_t *) block->bl_data + 1));
+		else
+			return (be64dec((uint8_t *) block->bl_data + 1));
+	}
+
+	return (0);
+}
+
+static char *
+find_object_name(Dwarf_Debug dbg, Dwarf_Die die)
+{
+	Dwarf_Die ret_die;
+	Dwarf_Attribute at;
+	Dwarf_Off off;
+	Dwarf_Error de;
+	const char *str;
+	char *name;
+
+	if (dwarf_attrval_string(die, DW_AT_name, &str, &de) == DW_DLV_OK) {
+		if ((name = strdup(str)) == NULL) {
+			warn("strdup");
+			return (NULL);
+		}
+		return (name);
+	}
+
+	if (dwarf_attr(die, DW_AT_specification, &at, &de) != DW_DLV_OK)
+		return (NULL);
+
+	if (dwarf_global_formref(at, &off, &de) != DW_DLV_OK)
+		return (NULL);
+
+	if (dwarf_offdie(dbg, off, &ret_die, &de) != DW_DLV_OK)
+		return (NULL);
+
+	return (find_object_name(dbg, ret_die));
+}
+
+static void
+search_line_attr(Dwarf_Debug dbg, struct func_info_head *func_info,
+    struct var_info_head *var_info, Dwarf_Die die, char **src_files,
+    Dwarf_Signed filecount)
+{
+	Dwarf_Attribute at;
+	Dwarf_Unsigned udata;
+	Dwarf_Half tag;
+	Dwarf_Block *block;
+	Dwarf_Bool flag;
+	Dwarf_Die ret_die;
+	Dwarf_Error de;
+	struct func_info_entry *func;
+	struct var_info_entry *var;
+	int ret;
+
+	if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
+		warnx("dwarf_tag failed: %s", dwarf_errmsg(de));
+		goto cont_search;
+	}
+
+	/* We're interested in DIEs which define functions or variables. */
+	if (tag != DW_TAG_subprogram && tag != DW_TAG_entry_point &&
+	    tag != DW_TAG_inlined_subroutine && tag != DW_TAG_variable)
+		goto cont_search;
+
+	if (tag == DW_TAG_variable) {
+
+		/* Ignore "artificial" variable. */
+		if (dwarf_attrval_flag(die, DW_AT_artificial, &flag, &de) ==
+		    DW_DLV_OK && flag)
+			goto cont_search;
+
+		/* Ignore pure declaration. */
+		if (dwarf_attrval_flag(die, DW_AT_declaration, &flag, &de) ==
+		    DW_DLV_OK && flag)
+			goto cont_search;
+
+		/* Ignore stack varaibles. */
+		if (dwarf_attrval_flag(die, DW_AT_external, &flag, &de) !=
+		    DW_DLV_OK || !flag)
+			goto cont_search;
+
+		if ((var = calloc(1, sizeof(*var))) == NULL) {
+			warn("calloc failed");
+			goto cont_search;
+		}
+
+		if (dwarf_attrval_unsigned(die, DW_AT_decl_file, &udata,
+		    &de) == DW_DLV_OK && udata > 0 &&
+		    (Dwarf_Signed) (udata - 1) < filecount) {
+			var->file = strdup(src_files[udata - 1]);
+			if (var->file == NULL) {
+				warn("strdup");
+				free(var);
+				goto cont_search;
+			}
+		}
+
+		if (dwarf_attrval_unsigned(die, DW_AT_decl_line, &udata, &de) ==
+		    DW_DLV_OK)
+			var->line = udata;
+
+		var->name = find_object_name(dbg, die);
+		if (var->name == NULL) {
+			if (var->file)
+				free(var->file);
+			free(var);
+			goto cont_search;
+		}
+
+		if (dwarf_attr(die, DW_AT_location, &at, &de) == DW_DLV_OK &&
+		    dwarf_formblock(at, &block, &de) == DW_DLV_OK) {
+			/*
+			 * Since we ignored stack variables, the rest are the
+			 * external varaibles which should always use DW_OP_addr
+			 * operator for DW_AT_location value.
+			 */
+			if (*((uint8_t *)block->bl_data) == DW_OP_addr)
+				var->addr = get_block_value(dbg, block);
+		}
+
+		SLIST_INSERT_HEAD(var_info, var, entries);
+
+	} else {
+
+		if ((func = calloc(1, sizeof(*func))) == NULL) {
+			warn("calloc failed");
+			goto cont_search;
+		}
+
+		/*
+		 * Note that dwarf_attrval_unsigned() handles DW_AT_abstract_origin
+		 * internally, so it can retrieve DW_AT_decl_file/DW_AT_decl_line
+		 * attributes for inlined functions as well.
+		 */
+		if (dwarf_attrval_unsigned(die, DW_AT_decl_file, &udata,
+		    &de) == DW_DLV_OK && udata > 0 &&
+		    (Dwarf_Signed) (udata - 1) < filecount) {
+			func->file = strdup(src_files[udata - 1]);
+			if (func->file == NULL) {
+				warn("strdup");
+				free(func);
+				goto cont_search;
+			}
+		}
+
+		if (dwarf_attrval_unsigned(die, DW_AT_decl_line, &udata, &de) ==
+		    DW_DLV_OK)
+			func->line = udata;
+
+		func->name = find_object_name(dbg, die);
+		if (func->name == NULL) {
+			if (func->file)
+				free(func->file);
+			free(func);
+			goto cont_search;
+		}
+
+		if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &udata, &de) ==
+		    DW_DLV_OK)
+			func->lowpc = udata;
+		if (dwarf_attrval_unsigned(die, DW_AT_high_pc, &udata, &de) ==
+		    DW_DLV_OK)
+			func->highpc = udata;
+
+		SLIST_INSERT_HEAD(func_info, func, entries);
+	}
+
+cont_search:
+
+	/* Search children. */
+	ret = dwarf_child(die, &ret_die, &de);
+	if (ret == DW_DLV_ERROR)
+		warnx("dwarf_child: %s", dwarf_errmsg(de));
+	else if (ret == DW_DLV_OK)
+		search_line_attr(dbg, func_info, var_info, ret_die, src_files,
+		    filecount);
+
+	/* Search sibling. */
+	ret = dwarf_siblingof(dbg, die, &ret_die, &de);
+	if (ret == DW_DLV_ERROR)
+		warnx("dwarf_siblingof: %s", dwarf_errmsg(de));
+	else if (ret == DW_DLV_OK)
+		search_line_attr(dbg, func_info, var_info, ret_die, src_files,
+		    filecount);
+
+	dwarf_dealloc(dbg, die, DW_DLA_DIE);
+}
+
+/*
+ * Read elf file and collect symbol information, sort them, print.
+ * Return 1 at failed, 0 at success.
+ */
+static int
+read_elf(Elf *elf, const char *filename, Elf_Kind kind)
+{
+	Dwarf_Debug dbg;
+	Dwarf_Die die;
+	Dwarf_Error de;
+	Dwarf_Half tag;
+	Elf_Arhdr *arhdr;
+	Elf_Scn *scn;
+	GElf_Shdr shdr;
+	GElf_Half i;
+	Dwarf_Line *lbuf;
+	Dwarf_Unsigned lineno;
+	Dwarf_Signed lcount, filecount;
+	Dwarf_Addr lineaddr;
+	struct sym_print_data p_data;
+	struct sym_head list_head;
+	struct line_info_head *line_info;
+	struct func_info_head *func_info;
+	struct var_info_head *var_info;
+	struct line_info_entry *lie;
+	struct func_info_entry *func;
+	struct var_info_entry *var;
+	const char *shname, *objname;
+	char *type_table, **sec_table, *sfile, **src_files;
+	size_t shstrndx, shnum, dynndx, strndx;
+	int ret, rtn, e_err;
+
+#define	OBJNAME	(objname == NULL ? filename : objname)
+
+	assert(filename != NULL && "filename is null");
+
+	STAILQ_INIT(&list_head);
+	type_table = NULL;
+	sec_table = NULL;
+	line_info = NULL;
+	func_info = NULL;
+	var_info = NULL;
+	objname = NULL;
+	dynndx = SHN_UNDEF;
+	strndx = SHN_UNDEF;
+	rtn = 0;
+
+	nm_elfclass = gelf_getclass(elf);
+
+	if (kind == ELF_K_AR) {
+		if ((arhdr = elf_getarhdr(elf)) == NULL)
+			goto next_cmd;
+		objname = arhdr->ar_name != NULL ? arhdr->ar_name :
+		    arhdr->ar_rawname;
+	}
+	if (!elf_getshnum(elf, &shnum)) {
+		if ((e_err = elf_errno()) != 0)
+			warnx("%s: %s", OBJNAME, "File format not recognized");
+		else
+			warnx("%s: cannot get section number", OBJNAME);
+		rtn = 1;
+		goto next_cmd;
+	}
+	if (shnum == 0) {
+		warnx("%s: has no section", OBJNAME);
+		rtn = 1;
+		goto next_cmd;
+	}
+	if (!elf_getshstrndx(elf, &shstrndx)) {
+		warnx("%s: cannot get str index", OBJNAME);
+		rtn = 1;
+		goto next_cmd;
+	}
+	/* type_table for type determine */
+	if ((type_table = malloc(sizeof(char) * shnum)) == NULL) {
+		warn("%s: malloc", OBJNAME);
+		rtn = 1;
+		goto next_cmd;
+	}
+	/* sec_table for section name to display in sysv format */
+	if ((sec_table = calloc(shnum, sizeof(char *))) == NULL) {
+		warn("%s: calloc", OBJNAME);
+		rtn = 1;
+		goto next_cmd;
+	}
+
+	type_table[0] = 'U';
+	if ((sec_table[0] = strdup("*UND*")) == NULL) {
+		warn("strdup");
+		goto next_cmd;
+	}
+
+	for (i = 1; i < shnum; ++i) {
+		type_table[i] = 'U';
+		if ((scn = elf_getscn(elf, i)) == NULL) {
+			if ((e_err = elf_errno()) != 0)
+				warnx("%s: %s", OBJNAME, elf_errmsg(e_err));
+			else
+				warnx("%s: cannot get section", OBJNAME);
+			rtn = 1;
+			goto next_cmd;
+		}
+		if (gelf_getshdr(scn, &shdr) == NULL)
+			goto next_cmd;
+
+		/*
+		 * Cannot test by type and attribute for dynstr, strtab
+		 */
+		shname = elf_strptr(elf, shstrndx, (size_t) shdr.sh_name);
+		if (shname != NULL) {
+			if ((sec_table[i] = strdup(shname)) == NULL) {
+				warn("strdup");
+				goto next_cmd;
+			}
+			if (!strncmp(shname, ".dynstr", 7)) {
+				dynndx = elf_ndxscn(scn);
+				if (dynndx == SHN_UNDEF) {
+					warnx("%s: elf_ndxscn failed: %s",
+					    OBJNAME, elf_errmsg(-1));
+					goto next_cmd;
+				}
+			}
+			if (!strncmp(shname, ".strtab", 7)) {
+				strndx = elf_ndxscn(scn);
+				if (strndx == SHN_UNDEF) {
+					warnx("%s: elf_ndxscn failed: %s",
+					    OBJNAME, elf_errmsg(-1));
+					goto next_cmd;
+				}					
+			}
+		} else {
+			sec_table[i] = strdup("*UND*");
+			if (sec_table[i] == NULL) {
+				warn("strdup");
+				goto next_cmd;
+			}
+		}
+
+
+		if (is_sec_text(&shdr))
+			type_table[i] = 'T';
+		else if (is_sec_data(&shdr)) {
+			if (is_sec_readonly(&shdr))
+				type_table[i] = 'R';
+			else
+				type_table[i] = 'D';
+		} else if (is_sec_nobits(&shdr))
+			type_table[i] = 'B';
+		else if (is_sec_debug(shname))
+			type_table[i] = 'N';
+		else if (is_sec_readonly(&shdr) && !is_sec_nobits(&shdr))
+			type_table[i] = 'n';
+	}
+
+	print_header(filename, objname);
+
+	if ((dynndx == SHN_UNDEF && nm_opts.print_symbol == PRINT_SYM_DYN) ||
+	    (strndx == SHN_UNDEF && nm_opts.print_symbol == PRINT_SYM_SYM)) {
+		warnx("%s: no symbols", OBJNAME);
+		/* This is not an error case */
+		goto next_cmd;
+	}
+
+	STAILQ_INIT(&list_head);
+
+	if (!nm_opts.debug_line)
+		goto process_sym;
+
+	/*
+	 * Collect dwarf line number information.
+	 */
+
+	if (dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dbg, &de) !=
+	    DW_DLV_OK) {
+		warnx("dwarf_elf_init failed: %s", dwarf_errmsg(de));
+		goto process_sym;
+	}
+
+	line_info = malloc(sizeof(struct line_info_head));
+	func_info = malloc(sizeof(struct func_info_head));
+	var_info = malloc(sizeof(struct var_info_head));
+	if (line_info != NULL)
+		SLIST_INIT(line_info);
+	if (func_info != NULL)
+		SLIST_INIT(func_info);
+	if (var_info != NULL)
+		SLIST_INIT(var_info);
+	if (line_info == NULL || func_info == NULL || var_info == NULL) {
+		warn("malloc");
+		(void) dwarf_finish(dbg, &de);
+		goto process_sym;
+	}
+
+	while ((ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL,
+	    &de)) ==  DW_DLV_OK) {
+		die = NULL;
+		while (dwarf_siblingof(dbg, die, &die, &de) == DW_DLV_OK) {
+			if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
+				warnx("dwarf_tag failed: %s",
+				    dwarf_errmsg(de));
+				continue;
+			}
+			/* XXX: What about DW_TAG_partial_unit? */
+			if (tag == DW_TAG_compile_unit)
+				break;
+		}
+		if (die == NULL) {
+			warnx("could not find DW_TAG_compile_unit die");
+			continue;
+		}
+
+		/* Retrieve source file list. */
+		ret = dwarf_srcfiles(die, &src_files, &filecount, &de);
+		if (ret == DW_DLV_ERROR)
+			warnx("dwarf_srclines: %s", dwarf_errmsg(de));
+		if (ret != DW_DLV_OK)
+			continue;
+
+		/*
+		 * Retrieve line number information from .debug_line section.
+		 */
+
+		ret = dwarf_srclines(die, &lbuf, &lcount, &de);
+		if (ret == DW_DLV_ERROR)
+			warnx("dwarf_srclines: %s", dwarf_errmsg(de));
+		if (ret != DW_DLV_OK)
+			goto line_attr;
+		for (i = 0; (Dwarf_Signed) i < lcount; i++) {
+			if (dwarf_lineaddr(lbuf[i], &lineaddr, &de)) {
+				warnx("dwarf_lineaddr: %s", dwarf_errmsg(de));
+				continue;
+			}
+			if (dwarf_lineno(lbuf[i], &lineno, &de)) {
+				warnx("dwarf_lineno: %s", dwarf_errmsg(de));
+				continue;
+			}
+			if (dwarf_linesrc(lbuf[i], &sfile, &de)) {
+				warnx("dwarf_linesrc: %s", dwarf_errmsg(de));
+				continue;
+			}
+			if ((lie = malloc(sizeof(*lie))) == NULL) {
+				warn("malloc");
+				continue;
+			}
+			lie->addr = lineaddr;
+			lie->line = lineno;
+			lie->file = strdup(sfile);
+			if (lie->file == NULL) {
+				warn("strdup");
+				free(lie);
+				continue;
+			}
+			SLIST_INSERT_HEAD(line_info, lie, entries);
+		}
+
+	line_attr:
+		/* Retrieve line number information from DIEs. */
+		search_line_attr(dbg, func_info, var_info, die, src_files, filecount);
+	}
+
+	(void) dwarf_finish(dbg, &de);
+
+process_sym:
+
+	p_data.list_num = get_sym(elf, &list_head, shnum, dynndx, strndx,
+	    type_table, (void *) sec_table, shnum);
+
+	if (p_data.list_num == 0)
+		goto next_cmd;
+
+	p_data.headp = &list_head;
+	p_data.sh_num = shnum;
+	p_data.t_table = type_table;
+	p_data.s_table = (void *) sec_table;
+	p_data.filename = filename;
+	p_data.objname = objname;
+
+	sym_list_print(&p_data, func_info, var_info, line_info);
+
+next_cmd:
+	if (nm_opts.debug_line) {
+		if (func_info != NULL) {
+			while (!SLIST_EMPTY(func_info)) {
+				func = SLIST_FIRST(func_info);
+				SLIST_REMOVE_HEAD(func_info, entries);
+				free(func->file);
+				free(func->name);
+				free(func);
+			}
+			free(func_info);
+			func_info = NULL;
+		}
+		if (var_info != NULL) {
+			while (!SLIST_EMPTY(var_info)) {
+				var = SLIST_FIRST(var_info);
+				SLIST_REMOVE_HEAD(var_info, entries);
+				free(var->file);
+				free(var->name);
+				free(var);
+			}
+			free(var_info);
+			var_info = NULL;
+		}
+		if (line_info != NULL) {
+			while (!SLIST_EMPTY(line_info)) {
+				lie = SLIST_FIRST(line_info);
+				SLIST_REMOVE_HEAD(line_info, entries);
+				free(lie->file);
+				free(lie);
+			}
+			free(line_info);
+			line_info = NULL;
+		}
+	}
+
+	if (sec_table != NULL)
+		for (i = 0; i < shnum; ++i)
+			free(sec_table[i]);
+	free(sec_table);
+	free(type_table);
+
+	sym_list_dest(&list_head);
+
+	return (rtn);
+
+#undef	OBJNAME
+}
+
+static int
+read_object(const char *filename)
+{
+	Elf *elf, *arf;
+	Elf_Cmd elf_cmd;
+	Elf_Kind kind;
+	int fd, rtn, e_err;
+
+	assert(filename != NULL && "filename is null");
+
+	if ((fd = open(filename, O_RDONLY)) == -1) {
+		warn("'%s'", filename);
+		return (1);
+	}
+
+	elf_cmd = ELF_C_READ;
+	if ((arf = elf_begin(fd, elf_cmd, (Elf *) NULL)) == NULL) {
+		if ((e_err = elf_errno()) != 0)
+			warnx("elf_begin error: %s", elf_errmsg(e_err));
+		else
+			warnx("elf_begin error");
+		close(fd);
+		return (1);
+	}
+
+	assert(arf != NULL && "arf is null.");
+
+	rtn = 0;
+	if ((kind = elf_kind(arf)) == ELF_K_NONE) {
+		warnx("%s: File format not recognized", filename);
+		elf_end(arf);
+		close(fd);
+		return (1);
+	}
+	if (kind == ELF_K_AR) {
+		if (nm_opts.print_name == PRINT_NAME_MULTI &&
+		    nm_opts.elem_print_fn == sym_elem_print_all)
+			printf("\n%s:\n", filename);
+		if (nm_opts.print_armap == true)
+			print_ar_index(fd, arf);
+	}
+
+	while ((elf = elf_begin(fd, elf_cmd, arf)) != NULL) {
+		rtn |= read_elf(elf, filename, kind);
+
+		/*
+		 * If file is not archive, elf_next return ELF_C_NULL and
+		 * stop the loop.
+		 */
+		elf_cmd = elf_next(elf);
+		elf_end(elf);
+	}
+
+	elf_end(arf);
+	close(fd);
+
+	return (rtn);
+}
+
+static int
+read_files(int argc, char **argv)
+{
+	int rtn = 0;
+
+	if (argc < 0 || argv == NULL)
+		return (1);
+
+	if (argc == 0)
+		rtn |= read_object(nm_info.def_filename);
+	else {
+		if (nm_opts.print_name == PRINT_NAME_NONE && argc > 1)
+			nm_opts.print_name = PRINT_NAME_MULTI;
+		while (argc > 0) {
+			rtn |= read_object(*argv);
+			--argc;
+			++argv;
+		}
+	}
+
+	return (rtn);
+}
+
+static void
+print_lineno(struct sym_entry *ep, struct func_info_head *func_info,
+    struct var_info_head *var_info, struct line_info_head *line_info)
+{
+	struct func_info_entry *func;
+	struct var_info_entry *var;
+	struct line_info_entry *lie;
+
+	/* For function symbol, search the function line information list.  */
+	if ((ep->sym->st_info & 0xf) == STT_FUNC && func_info != NULL) {
+		SLIST_FOREACH(func, func_info, entries) {
+			if (func->name != NULL &&
+			    !strcmp(ep->name, func->name) &&
+			    ep->sym->st_value >= func->lowpc &&
+			    ep->sym->st_value < func->highpc) {
+				printf("\t%s:%" PRIu64, func->file, func->line);
+				return;
+			}
+		}
+	}
+
+	/* For variable symbol, search the variable line information list.  */
+	if ((ep->sym->st_info & 0xf) == STT_OBJECT && var_info != NULL) {
+		SLIST_FOREACH(var, var_info, entries) {
+			if (!strcmp(ep->name, var->name) &&
+			    ep->sym->st_value == var->addr) {
+				printf("\t%s:%" PRIu64, var->file, var->line);
+				return;
+			}
+		}
+	}
+
+	/* Otherwise search line number information the .debug_line section. */
+	if (line_info != NULL) {
+		SLIST_FOREACH(lie, line_info, entries) {
+			if (ep->sym->st_value == lie->addr) {
+				printf("\t%s:%" PRIu64, lie->file, lie->line);
+				return;
+			}
+		}
+	}
+}
+
+static void
+set_opt_value_print_fn(enum radix t)
+{
+
+	switch (t) {
+	case RADIX_OCT:
+		nm_opts.value_print_fn = &sym_value_oct_print;
+		nm_opts.size_print_fn = &sym_size_oct_print;
+
+		break;
+	case RADIX_DEC:
+		nm_opts.value_print_fn = &sym_value_dec_print;
+		nm_opts.size_print_fn = &sym_size_dec_print;
+
+		break;
+	case RADIX_HEX:
+	default :
+		nm_opts.value_print_fn = &sym_value_hex_print;
+		nm_opts.size_print_fn  = &sym_size_hex_print;
+	}
+
+	assert(nm_opts.value_print_fn != NULL &&
+	    "nm_opts.value_print_fn is null");
+}
+
+static void
+sym_elem_print_all(char type, const char *sec, const GElf_Sym *sym,
+    const char *name)
+{
+
+	if (sec == NULL || sym == NULL || name == NULL ||
+	    nm_opts.value_print_fn == NULL)
+		return;
+
+	if (IS_UNDEF_SYM_TYPE(type)) {
+		if (nm_opts.t == RADIX_HEX && nm_elfclass == ELFCLASS32)
+			printf("%-8s", "");
+		else
+			printf("%-16s", "");
+	} else {
+		switch ((nm_opts.sort_fn == & cmp_size ? 2 : 0) +
+		    nm_opts.print_size) {
+		case 3:
+			if (sym->st_size != 0) {
+				nm_opts.value_print_fn(sym);
+				printf(" ");
+				nm_opts.size_print_fn(sym);
+			}
+			break;
+
+		case 2:
+			if (sym->st_size != 0)
+				nm_opts.size_print_fn(sym);
+			break;
+
+		case 1:
+			nm_opts.value_print_fn(sym);
+			if (sym->st_size != 0) {
+				printf(" ");
+				nm_opts.size_print_fn(sym);
+			}
+			break;
+
+		case 0:
+		default:
+			nm_opts.value_print_fn(sym);
+		}
+	}
+
+	printf(" %c ", type);
+	PRINT_DEMANGLED_NAME("%s", name);
+}
+
+static void
+sym_elem_print_all_portable(char type, const char *sec, const GElf_Sym *sym,
+    const char *name)
+{
+
+	if (sec == NULL || sym == NULL || name == NULL ||
+	    nm_opts.value_print_fn == NULL)
+		return;
+
+	PRINT_DEMANGLED_NAME("%s", name);
+	printf(" %c ", type);
+	if (!IS_UNDEF_SYM_TYPE(type)) {
+		nm_opts.value_print_fn(sym);
+		printf(" ");
+		if (sym->st_size != 0)
+			nm_opts.size_print_fn(sym);
+	} else
+		printf("        ");
+}
+
+static void
+sym_elem_print_all_sysv(char type, const char *sec, const GElf_Sym *sym,
+    const char *name)
+{
+
+	if (sec == NULL || sym == NULL || name == NULL ||
+	    nm_opts.value_print_fn == NULL)
+		return;
+
+	PRINT_DEMANGLED_NAME("%-20s|", name);
+	if (IS_UNDEF_SYM_TYPE(type))
+		printf("                ");
+	else
+		nm_opts.value_print_fn(sym);
+
+	printf("|   %c  |", type);
+
+	switch (sym->st_info & 0xf) {
+	case STT_OBJECT:
+		printf("%18s|", "OBJECT");
+		break;
+
+	case STT_FUNC:
+		printf("%18s|", "FUNC");
+		break;
+
+	case STT_SECTION:
+		printf("%18s|", "SECTION");
+		break;
+
+	case STT_FILE:
+		printf("%18s|", "FILE");
+		break;
+
+	case STT_LOPROC:
+		printf("%18s|", "LOPROC");
+		break;
+
+	case STT_HIPROC:
+		printf("%18s|", "HIPROC");
+		break;
+
+	case STT_NOTYPE:
+	default:
+		printf("%18s|", "NOTYPE");
+	}
+
+	if (sym->st_size != 0)
+		nm_opts.size_print_fn(sym);
+	else
+		printf("                ");
+
+	printf("|     |%s", sec);
+}
+
+static int
+sym_elem_def(char type, const GElf_Sym *sym, const char *name)
+{
+
+	assert(IS_SYM_TYPE((unsigned char) type));
+
+	UNUSED(sym);
+	UNUSED(name);
+
+	return (!IS_UNDEF_SYM_TYPE((unsigned char) type));
+}
+
+static int
+sym_elem_global(char type, const GElf_Sym *sym, const char *name)
+{
+
+	assert(IS_SYM_TYPE((unsigned char) type));
+
+	UNUSED(sym);
+	UNUSED(name);
+
+	/* weak symbols resemble global. */
+	return (isupper((unsigned char) type) || type == 'w');
+}
+
+static int
+sym_elem_global_static(char type, const GElf_Sym *sym, const char *name)
+{
+	unsigned char info;
+
+	assert(sym != NULL);
+
+	UNUSED(type);
+	UNUSED(name);
+
+	info = sym->st_info >> 4;
+
+	return (info == STB_LOCAL ||
+	    info == STB_GLOBAL ||
+	    info == STB_WEAK);
+}
+
+static int
+sym_elem_nondebug(char type, const GElf_Sym *sym, const char *name)
+{
+
+	assert(sym != NULL);
+
+	UNUSED(type);
+	UNUSED(name);
+
+	if (sym->st_value == 0 && (sym->st_info & 0xf) == STT_FILE)
+		return (0);
+	if (sym->st_name == 0)
+		return (0);
+
+	return (1);
+}
+
+static int
+sym_elem_nonzero_size(char type, const GElf_Sym *sym, const char *name)
+{
+
+	assert(sym != NULL);
+
+	UNUSED(type);
+	UNUSED(name);
+
+	return (sym->st_size > 0);
+}
+
+static int
+sym_elem_undef(char type, const GElf_Sym *sym, const char *name)
+{
+
+	assert(IS_SYM_TYPE((unsigned char) type));
+
+	UNUSED(sym);
+	UNUSED(name);
+
+	return (IS_UNDEF_SYM_TYPE((unsigned char) type));
+}
+
+static void
+sym_list_dest(struct sym_head *headp)
+{
+	struct sym_entry *ep, *ep_n;
+
+	if (headp == NULL)
+		return;
+
+	ep = STAILQ_FIRST(headp);
+	while (ep != NULL) {
+		ep_n = STAILQ_NEXT(ep, sym_entries);
+		free(ep->sym);
+		free(ep->name);
+		free(ep);
+		ep = ep_n;
+	}
+}
+
+static int
+sym_list_insert(struct sym_head *headp, const char *name, const GElf_Sym *sym)
+{
+	struct sym_entry *e;
+
+	if (headp == NULL || name == NULL || sym == NULL)
+		return (0);
+	if ((e = malloc(sizeof(struct sym_entry))) == NULL) {
+		warn("malloc");
+		return (0);
+	}
+	if ((e->name = strdup(name)) == NULL) {
+		warn("strdup");
+		free(e);
+		return (0);
+	}
+	if ((e->sym = malloc(sizeof(GElf_Sym))) == NULL) {
+		warn("malloc");
+		free(e->name);
+		free(e);
+		return (0);
+	}
+
+	memcpy(e->sym, sym, sizeof(GElf_Sym));
+
+	/* Display size instead of value for common symbol. */
+	if (sym->st_shndx == SHN_COMMON)
+		e->sym->st_value = sym->st_size;
+
+	STAILQ_INSERT_TAIL(headp, e, sym_entries);
+
+	return (1);
+}
+
+/* If file has not .debug_info, line_info will be NULL */
+static void
+sym_list_print(struct sym_print_data *p, struct func_info_head *func_info,
+    struct var_info_head *var_info, struct line_info_head *line_info)
+{
+	struct sym_entry *e_v;
+	size_t si;
+	int i;
+
+	if (p == NULL || CHECK_SYM_PRINT_DATA(p))
+		return;
+	if ((e_v = sym_list_sort(p)) == NULL)
+		return;
+	if (nm_opts.sort_reverse == false)
+		for (si = 0; si != p->list_num; ++si)
+			sym_list_print_each(&e_v[si], p, func_info, var_info,
+			    line_info);
+	else
+		for (i = p->list_num - 1; i != -1; --i)
+			sym_list_print_each(&e_v[i], p, func_info, var_info,
+			    line_info);
+
+	free(e_v);
+}
+
+/* If file has not .debug_info, line_info will be NULL */
+static void
+sym_list_print_each(struct sym_entry *ep, struct sym_print_data *p,
+    struct func_info_head *func_info, struct var_info_head *var_info,
+    struct line_info_head *line_info)
+{
+	const char *sec;
+	char type;
+
+	if (ep == NULL || CHECK_SYM_PRINT_DATA(p))
+		return;
+
+	assert(ep->name != NULL);
+	assert(ep->sym != NULL);
+
+	type = get_sym_type(ep->sym, p->t_table);
+
+	if (nm_opts.print_name == PRINT_NAME_FULL) {
+		printf("%s", p->filename);
+		if (nm_opts.elem_print_fn == &sym_elem_print_all_portable) {
+			if (p->objname != NULL)
+				printf("[%s]", p->objname);
+			printf(": ");
+		} else {
+			if (p->objname != NULL)
+				printf(":%s", p->objname);
+			printf(":");
+		}
+	}
+
+	switch (ep->sym->st_shndx) {
+	case SHN_LOPROC:
+		/* LOPROC or LORESERVE */
+		sec = "*LOPROC*";
+		break;
+	case SHN_HIPROC:
+		sec = "*HIPROC*";
+		break;
+	case SHN_LOOS:
+		sec = "*LOOS*";
+		break;
+	case SHN_HIOS:
+		sec = "*HIOS*";
+		break;
+	case SHN_ABS:
+		sec = "*ABS*";
+		break;
+	case SHN_COMMON:
+		sec = "*COM*";
+		break;
+	case SHN_HIRESERVE:
+		/* HIRESERVE or XINDEX */
+		sec = "*HIRESERVE*";
+		break;
+	default:
+		if (ep->sym->st_shndx > p->sh_num)
+			return;
+		sec = p->s_table[ep->sym->st_shndx];
+		break;
+	}
+
+	nm_opts.elem_print_fn(type, sec, ep->sym, ep->name);
+
+	if (nm_opts.debug_line == true && !IS_UNDEF_SYM_TYPE(type))
+		print_lineno(ep, func_info, var_info, line_info);
+
+	printf("\n");
+}
+
+static struct sym_entry	*
+sym_list_sort(struct sym_print_data *p)
+{
+	struct sym_entry *ep, *e_v;
+	int idx;
+
+	if (p == NULL || CHECK_SYM_PRINT_DATA(p))
+		return (NULL);
+
+	if ((e_v = malloc(sizeof(struct sym_entry) * p->list_num)) == NULL) {
+		warn("malloc");
+		return (NULL);
+	}
+
+	idx = 0;
+	STAILQ_FOREACH(ep, p->headp, sym_entries) {
+		if (ep->name != NULL && ep->sym != NULL) {
+			e_v[idx].name = ep->name;
+			e_v[idx].sym = ep->sym;
+			++idx;
+		}
+	}
+
+	assert((size_t)idx == p->list_num);
+
+	if (nm_opts.sort_fn != &cmp_none) {
+		nm_print_data = p;
+		assert(nm_print_data != NULL);
+		qsort(e_v, p->list_num, sizeof(struct sym_entry),
+		    nm_opts.sort_fn);
+	}
+
+	return (e_v);
+}
+
+static void
+sym_size_oct_print(const GElf_Sym *sym)
+{
+
+	assert(sym != NULL && "sym is null");
+	printf("%016" PRIo64, sym->st_size);
+}
+
+static void
+sym_size_hex_print(const GElf_Sym *sym)
+{
+
+	assert(sym != NULL && "sym is null");
+	if (nm_elfclass == ELFCLASS32)
+		printf("%08" PRIx64, sym->st_size);
+	else
+		printf("%016" PRIx64, sym->st_size);
+}
+
+static void
+sym_size_dec_print(const GElf_Sym *sym)
+{
+
+	assert(sym != NULL && "sym is null");
+	printf("%016" PRId64, sym->st_size);
+}
+
+static void
+sym_value_oct_print(const GElf_Sym *sym)
+{
+
+	assert(sym != NULL && "sym is null");
+	printf("%016" PRIo64, sym->st_value);
+}
+
+static void
+sym_value_hex_print(const GElf_Sym *sym)
+{
+
+	assert(sym != NULL && "sym is null");
+	if (nm_elfclass == ELFCLASS32)
+		printf("%08" PRIx64, sym->st_value);
+	else
+		printf("%016" PRIx64, sym->st_value);
+}
+
+static void
+sym_value_dec_print(const GElf_Sym *sym)
+{
+
+	assert(sym != NULL && "sym is null");
+	printf("%016" PRId64, sym->st_value);
+}
+
+static void
+usage(int exitcode)
+{
+
+	printf("Usage: %s [options] file ...\
+\n  Display symbolic information in file.\n\
+\n  Options: \
+\n  -A, --print-file-name     Write the full pathname or library name of an\
+\n                            object on each line.\
+\n  -a, --debug-syms          Display all symbols include debugger-only\
+\n                            symbols.", nm_info.name);
+	printf("\
+\n  -B                        Equivalent to specifying \"--format=bsd\".\
+\n  -C, --demangle[=style]    Decode low-level symbol names.\
+\n      --no-demangle         Do not demangle low-level symbol names.\
+\n  -D, --dynamic             Display only dynamic symbols.\
+\n  -e                        Display only global and static symbols.");
+	printf("\
+\n  -f                        Produce full output (default).\
+\n      --format=format       Display output in specific format.  Allowed\
+\n                            formats are: \"bsd\", \"posix\" and \"sysv\".\
+\n  -g, --extern-only         Display only global symbol information.\
+\n  -h, --help                Show this help message.\
+\n  -l, --line-numbers        Display filename and linenumber using\
+\n                            debugging information.\
+\n  -n, --numeric-sort        Sort symbols numerically by value.");
+	printf("\
+\n  -o                        Write numeric values in octal. Equivalent to\
+\n                            specifying \"-t o\".\
+\n  -p, --no-sort             Do not sort symbols.\
+\n  -P                        Write information in a portable output format.\
+\n                            Equivalent to specifying \"--format=posix\".\
+\n  -r, --reverse-sort        Reverse the order of the sort.\
+\n  -S, --print-size          Print symbol sizes instead values.\
+\n  -s, --print-armap         Include an index of archive members.\
+\n      --size-sort           Sort symbols by size.");
+	printf("\
+\n  -t, --radix=format        Write each numeric value in the specified\
+\n                            format:\
+\n                               d   In decimal,\
+\n                               o   In octal,\
+\n                               x   In hexadecimal.");
+	printf("\
+\n  -u, --undefined-only      Display only undefined symbols.\
+\n      --defined-only        Display only defined symbols.\
+\n  -V, --version             Show the version identifier for %s.\
+\n  -v                        Sort output by value.\
+\n  -x                        Write numeric values in hexadecimal.\
+\n                            Equivalent to specifying \"-t x\".",
+	    nm_info.name);
+	printf("\n\
+\n  The default options are: output in bsd format, use a hexadecimal radix,\
+\n  sort by symbol name, do not demangle names.\n");
+
+	exit(exitcode);
+}
+
+/*
+ * Display symbolic information in file.
+ * Return 0 at success, >0 at failed.
+ */
+int
+main(int argc, char **argv)
+{
+	int rtn;
+
+	global_init();
+	get_opt(argc, argv);
+	rtn = read_files(argc - optind, argv + optind);
+	global_dest();
+
+	exit(rtn);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/nm/os.NetBSD.mk	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,2 @@
+# TODO(#511): Revert after the source tree is -Wconversion clean.
+WARNS=5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/readelf/Makefile	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,15 @@
+# $Id: Makefile 2076 2011-10-27 03:50:33Z jkoshy $
+
+TOP=	..
+
+PROG=	readelf
+SRCS=	readelf.c
+
+WARNS?=	6
+
+DPADD=	${LIBDWARF} ${LIBELF}
+LDADD=	-ldwarf -lelftc -lelf
+
+MAN1=	readelf.1
+
+.include "${TOP}/mk/elftoolchain.prog.mk"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/readelf/os.NetBSD.mk	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,2 @@
+# TODO(#511): Revert after the source tree is -Wconversion clean.
+WARNS=5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/readelf/readelf.1	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,197 @@
+.\" Copyright (c) 2009,2011 Joseph Koshy <jkoshy@users.sourceforge.net>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer
+.\"    in this position and unchanged.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $Id: readelf.1 3486 2016-08-22 14:10:05Z emaste $
+.\"
+.Dd September 13, 2012
+.Os
+.Dt READELF 1
+.Sh NAME
+.Nm readelf
+.Nd display information about ELF objects
+.Sh SYNOPSIS
+.Nm
+.Op Fl a | Fl -all
+.Op Fl c | Fl -archive-index
+.Op Fl d | Fl -dynamic
+.Op Fl e | Fl -headers
+.Op Fl g | Fl -section-groups
+.Op Fl h | Fl -file-header
+.Op Fl l | Fl -program-headers
+.Op Fl n | Fl -notes
+.Op Fl p Ar section | Fl -string-dump Ns = Ns Ar section
+.Op Fl r | Fl -relocs
+.Op Fl t | Fl -section-details
+.Op Fl v | Fl -version
+.Oo
+.Fl w Ns Oo Ns Ar afilmoprsFLR Ns Oc |
+.Fl -debug-dump Ns Op Ns = Ns Ar long-option-name , Ns ...
+.Oc
+.Op Fl x Ar section | Fl -hex-dump Ns = Ns Ar section
+.Op Fl A | Fl -arch-specific
+.Op Fl D | Fl -use-dynamic
+.Op Fl H | Fl -help
+.Op Fl I | Fl -histogram
+.Op Fl N | -full-section-name
+.Op Fl S | Fl -sections | Fl -section-headers
+.Op Fl V | Fl -version-info
+.Op Fl W | Fl -wide
+.Ar file...
+.Sh DESCRIPTION
+The
+.Nm
+utility displays information about ELF objects and
+.Xr ar 1
+archives.
+.Pp
+The
+.Nm
+utility recognizes the following options:
+.Bl -tag -width indent
+.It Fl a | Fl -all
+Turn on the following flags:
+.Fl d ,
+.Fl h ,
+.Fl I ,
+.Fl l ,
+.Fl r ,
+.Fl s ,
+.Fl A ,
+.Fl S
+and
+.Fl V .
+.It Fl c | Fl -archive-index
+Print the archive symbol table for archives.
+.It Fl d | Fl -dynamic
+Print the contents of the
+.Li SHT_DYNAMIC
+sections in the ELF object.
+.It Fl e | Fl -headers
+Print all program, file and section headers in the ELF object.
+.It Fl g | Fl -section-groups
+Print the contents of the section groups in the ELF object.
+.It Fl h | Fl -file-header
+Print the file header of the ELF object.
+.It Fl l | Fl -program-headers
+Print the content of the program header table for the object.
+.It Fl n | Fl -notes
+Print the contents of
+.Li PT_NOTE
+segments or
+.Li SHT_NOTE
+sections present in the ELF object.
+.It Fl p Ar section | Fl -string-dump Ns = Ns Ar section
+Print the contents of the specified section as printable strings.
+The argument
+.Ar section
+should be the name of a section or a numeric section index.
+.It Fl r | Fl -relocs
+Print relocation information.
+.It Fl s | Fl -syms | Fl -symbols
+Print symbol tables.
+.It Fl t | Fl -section-details
+Print additional information about sections, such as the flags
+fields in section headers.
+.It Fl v | Fl -version
+Prints a version identifier for
+.Nm
+and exits.
+.It Fl w Ns Oo afilmoprsFLR Oc | Xo
+.Fl -debug-dump Ns Op Ns = Ns Ar long-option-name , Ns ...
+.Xc
+Display DWARF information.
+The
+.Fl w
+option is used with the short options in the following
+table; the
+.Fl -debug-dump
+option is used with a comma-separated list of the corresponding long
+option names:
+.Bl -column ".Em Short Option" "aranges|ranges"
+.It Em Short Option Ta Em Long Option Ta Em Description
+.It a Ta abbrev Ta Show abbreviation information.
+.It f Ta frames Ta Show frame information, displaying frame instructions.
+.It i Ta info Ta Show debugging information entries.
+.It l Ta rawline Ta Show line information in raw form.
+.It m Ta macro Ta Show macro information.
+.It o Ta loc Ta Show location list information.
+.It p Ta pubnames Ta Show global names.
+.It r Ta aranges|ranges Ta Show address range information.
+.It s Ta str Ta Show the debug string table.
+.It F Ta frames-interp Ta Show frame information, displaying register rules.
+.It L Ta decodedline Ta Show line information in decoded form.
+.It R Ta Ranges Ta Show range lists.
+.El
+.Pp
+If no sub-options are specified, the default is to show information
+corresponding to the
+.Ar a , f , i, l , o , p , r , s
+and
+.Ar R
+short options.
+.It Fl x Ar section | Fl -hex-dump Ns = Ns Ar section
+Display the contents of the specified section in hexadecimal.
+The argument
+.Ar section
+should be the name of a section or a numeric section index.
+.It Fl A | Fl -arch-specific
+This option is accepted but is currently unimplemented.
+.It Fl D | Fl -use-dynamic
+Print the symbol table specified by the
+.Li DT_SYMTAB
+entry in the
+.Dq Li .dynamic
+section.
+.It Fl H | Fl -help
+Print a help message.
+.It Fl I | Fl -histogram
+Print information on bucket list lengths for sections of type
+.Li SHT_HASH
+and
+.Li SHT_GNU_HASH .
+.It Fl N | Fl -full-section-name
+This option is accepted but is currently unimplemented.
+.It Fl S | Fl -sections | Fl -section-headers
+Print information in the section headers for each ELF object.
+.It Fl V | Fl -version-info
+Print symbol versioning information.
+.It Fl W | Fl -wide
+Print information about ELF structures using one long line per
+structure.
+If this option is not specified,
+.Nm
+will list information in the headers of 64 bit ELF objects on two
+separate lines.
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh SEE ALSO
+.Xr nm 1 ,
+.Xr addr2line 1 ,
+.Xr elfcopy 1 ,
+.Sh AUTHORS
+The
+.Nm
+utility was written by
+.An Kai Wang Aq Mt kaiwang27@users.sourceforge.net .
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/readelf/readelf.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,7412 @@
+/*-
+ * Copyright (c) 2009-2015 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <ar.h>
+#include <assert.h>
+#include <ctype.h>
+#include <dwarf.h>
+#include <err.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <getopt.h>
+#include <libdwarf.h>
+#include <libelftc.h>
+#include <libgen.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "_elftc.h"
+
+ELFTC_VCSID("$Id: readelf.c 3580 2017-09-15 23:29:59Z emaste $");
+
+/* Backwards compatability for older FreeBSD releases. */
+#ifndef	STB_GNU_UNIQUE
+#define	STB_GNU_UNIQUE 10
+#endif
+#ifndef	STT_SPARC_REGISTER
+#define	STT_SPARC_REGISTER 13
+#endif
+
+
+/*
+ * readelf(1) options.
+ */
+#define	RE_AA	0x00000001
+#define	RE_C	0x00000002
+#define	RE_DD	0x00000004
+#define	RE_D	0x00000008
+#define	RE_G	0x00000010
+#define	RE_H	0x00000020
+#define	RE_II	0x00000040
+#define	RE_I	0x00000080
+#define	RE_L	0x00000100
+#define	RE_NN	0x00000200
+#define	RE_N	0x00000400
+#define	RE_P	0x00000800
+#define	RE_R	0x00001000
+#define	RE_SS	0x00002000
+#define	RE_S	0x00004000
+#define	RE_T	0x00008000
+#define	RE_U	0x00010000
+#define	RE_VV	0x00020000
+#define	RE_WW	0x00040000
+#define	RE_W	0x00080000
+#define	RE_X	0x00100000
+
+/*
+ * dwarf dump options.
+ */
+#define	DW_A	0x00000001
+#define	DW_FF	0x00000002
+#define	DW_F	0x00000004
+#define	DW_I	0x00000008
+#define	DW_LL	0x00000010
+#define	DW_L	0x00000020
+#define	DW_M	0x00000040
+#define	DW_O	0x00000080
+#define	DW_P	0x00000100
+#define	DW_RR	0x00000200
+#define	DW_R	0x00000400
+#define	DW_S	0x00000800
+
+#define	DW_DEFAULT_OPTIONS (DW_A | DW_F | DW_I | DW_L | DW_O | DW_P | \
+	    DW_R | DW_RR | DW_S)
+
+/*
+ * readelf(1) run control flags.
+ */
+#define	DISPLAY_FILENAME	0x0001
+
+/*
+ * Internal data structure for sections.
+ */
+struct section {
+	const char	*name;		/* section name */
+	Elf_Scn		*scn;		/* section scn */
+	uint64_t	 off;		/* section offset */
+	uint64_t	 sz;		/* section size */
+	uint64_t	 entsize;	/* section entsize */
+	uint64_t	 align;		/* section alignment */
+	uint64_t	 type;		/* section type */
+	uint64_t	 flags;		/* section flags */
+	uint64_t	 addr;		/* section virtual addr */
+	uint32_t	 link;		/* section link ndx */
+	uint32_t	 info;		/* section info ndx */
+};
+
+struct dumpop {
+	union {
+		size_t si;		/* section index */
+		const char *sn;		/* section name */
+	} u;
+	enum {
+		DUMP_BY_INDEX = 0,
+		DUMP_BY_NAME
+	} type;				/* dump type */
+#define HEX_DUMP	0x0001
+#define STR_DUMP	0x0002
+	int op;				/* dump operation */
+	STAILQ_ENTRY(dumpop) dumpop_list;
+};
+
+struct symver {
+	const char *name;
+	int type;
+};
+
+/*
+ * Structure encapsulates the global data for readelf(1).
+ */
+struct readelf {
+	const char	 *filename;	/* current processing file. */
+	int		  options;	/* command line options. */
+	int		  flags;	/* run control flags. */
+	int		  dop;		/* dwarf dump options. */
+	Elf		 *elf;		/* underlying ELF descriptor. */
+	Elf		 *ar;		/* archive ELF descriptor. */
+	Dwarf_Debug	  dbg;		/* DWARF handle. */
+	Dwarf_Half	  cu_psize;	/* DWARF CU pointer size. */
+	Dwarf_Half	  cu_osize;	/* DWARF CU offset size. */
+	Dwarf_Half	  cu_ver;	/* DWARF CU version. */
+	GElf_Ehdr	  ehdr;		/* ELF header. */
+	int		  ec;		/* ELF class. */
+	size_t		  shnum;	/* #sections. */
+	struct section	 *vd_s;		/* Verdef section. */
+	struct section	 *vn_s;		/* Verneed section. */
+	struct section	 *vs_s;		/* Versym section. */
+	uint16_t	 *vs;		/* Versym array. */
+	int		  vs_sz;	/* Versym array size. */
+	struct symver	 *ver;		/* Version array. */
+	int		  ver_sz;	/* Size of version array. */
+	struct section	 *sl;		/* list of sections. */
+	STAILQ_HEAD(, dumpop) v_dumpop; /* list of dump ops. */
+	uint64_t	(*dw_read)(Elf_Data *, uint64_t *, int);
+	uint64_t	(*dw_decode)(uint8_t **, int);
+};
+
+enum options
+{
+	OPTION_DEBUG_DUMP
+};
+
+static struct option longopts[] = {
+	{"all", no_argument, NULL, 'a'},
+	{"arch-specific", no_argument, NULL, 'A'},
+	{"archive-index", no_argument, NULL, 'c'},
+	{"debug-dump", optional_argument, NULL, OPTION_DEBUG_DUMP},
+	{"dynamic", no_argument, NULL, 'd'},
+	{"file-header", no_argument, NULL, 'h'},
+	{"full-section-name", no_argument, NULL, 'N'},
+	{"headers", no_argument, NULL, 'e'},
+	{"help", no_argument, 0, 'H'},
+	{"hex-dump", required_argument, NULL, 'x'},
+	{"histogram", no_argument, NULL, 'I'},
+	{"notes", no_argument, NULL, 'n'},
+	{"program-headers", no_argument, NULL, 'l'},
+	{"relocs", no_argument, NULL, 'r'},
+	{"sections", no_argument, NULL, 'S'},
+	{"section-headers", no_argument, NULL, 'S'},
+	{"section-groups", no_argument, NULL, 'g'},
+	{"section-details", no_argument, NULL, 't'},
+	{"segments", no_argument, NULL, 'l'},
+	{"string-dump", required_argument, NULL, 'p'},
+	{"symbols", no_argument, NULL, 's'},
+	{"syms", no_argument, NULL, 's'},
+	{"unwind", no_argument, NULL, 'u'},
+	{"use-dynamic", no_argument, NULL, 'D'},
+	{"version-info", no_argument, 0, 'V'},
+	{"version", no_argument, 0, 'v'},
+	{"wide", no_argument, 0, 'W'},
+	{NULL, 0, NULL, 0}
+};
+
+struct eflags_desc {
+	uint64_t flag;
+	const char *desc;
+};
+
+struct mips_option {
+	uint64_t flag;
+	const char *desc;
+};
+
+static void add_dumpop(struct readelf *re, size_t si, const char *sn, int op,
+    int t);
+static const char *aeabi_adv_simd_arch(uint64_t simd);
+static const char *aeabi_align_needed(uint64_t an);
+static const char *aeabi_align_preserved(uint64_t ap);
+static const char *aeabi_arm_isa(uint64_t ai);
+static const char *aeabi_cpu_arch(uint64_t arch);
+static const char *aeabi_cpu_arch_profile(uint64_t pf);
+static const char *aeabi_div(uint64_t du);
+static const char *aeabi_enum_size(uint64_t es);
+static const char *aeabi_fp_16bit_format(uint64_t fp16);
+static const char *aeabi_fp_arch(uint64_t fp);
+static const char *aeabi_fp_denormal(uint64_t fd);
+static const char *aeabi_fp_exceptions(uint64_t fe);
+static const char *aeabi_fp_hpext(uint64_t fh);
+static const char *aeabi_fp_number_model(uint64_t fn);
+static const char *aeabi_fp_optm_goal(uint64_t fog);
+static const char *aeabi_fp_rounding(uint64_t fr);
+static const char *aeabi_hardfp(uint64_t hfp);
+static const char *aeabi_mpext(uint64_t mp);
+static const char *aeabi_optm_goal(uint64_t og);
+static const char *aeabi_pcs_config(uint64_t pcs);
+static const char *aeabi_pcs_got(uint64_t got);
+static const char *aeabi_pcs_r9(uint64_t r9);
+static const char *aeabi_pcs_ro(uint64_t ro);
+static const char *aeabi_pcs_rw(uint64_t rw);
+static const char *aeabi_pcs_wchar_t(uint64_t wt);
+static const char *aeabi_t2ee(uint64_t t2ee);
+static const char *aeabi_thumb_isa(uint64_t ti);
+static const char *aeabi_fp_user_exceptions(uint64_t fu);
+static const char *aeabi_unaligned_access(uint64_t ua);
+static const char *aeabi_vfp_args(uint64_t va);
+static const char *aeabi_virtual(uint64_t vt);
+static const char *aeabi_wmmx_arch(uint64_t wmmx);
+static const char *aeabi_wmmx_args(uint64_t wa);
+static const char *elf_class(unsigned int class);
+static const char *elf_endian(unsigned int endian);
+static const char *elf_machine(unsigned int mach);
+static const char *elf_osabi(unsigned int abi);
+static const char *elf_type(unsigned int type);
+static const char *elf_ver(unsigned int ver);
+static const char *dt_type(unsigned int mach, unsigned int dtype);
+static void dump_ar(struct readelf *re, int);
+static void dump_arm_attributes(struct readelf *re, uint8_t *p, uint8_t *pe);
+static void dump_attributes(struct readelf *re);
+static uint8_t *dump_compatibility_tag(uint8_t *p, uint8_t *pe);
+static void dump_dwarf(struct readelf *re);
+static void dump_dwarf_abbrev(struct readelf *re);
+static void dump_dwarf_aranges(struct readelf *re);
+static void dump_dwarf_block(struct readelf *re, uint8_t *b,
+    Dwarf_Unsigned len);
+static void dump_dwarf_die(struct readelf *re, Dwarf_Die die, int level);
+static void dump_dwarf_frame(struct readelf *re, int alt);
+static void dump_dwarf_frame_inst(struct readelf *re, Dwarf_Cie cie,
+    uint8_t *insts, Dwarf_Unsigned len, Dwarf_Unsigned caf, Dwarf_Signed daf,
+    Dwarf_Addr pc, Dwarf_Debug dbg);
+static int dump_dwarf_frame_regtable(struct readelf *re, Dwarf_Fde fde,
+    Dwarf_Addr pc, Dwarf_Unsigned func_len, Dwarf_Half cie_ra);
+static void dump_dwarf_frame_section(struct readelf *re, struct section *s,
+    int alt);
+static void dump_dwarf_info(struct readelf *re, Dwarf_Bool is_info);
+static void dump_dwarf_macinfo(struct readelf *re);
+static void dump_dwarf_line(struct readelf *re);
+static void dump_dwarf_line_decoded(struct readelf *re);
+static void dump_dwarf_loc(struct readelf *re, Dwarf_Loc *lr);
+static void dump_dwarf_loclist(struct readelf *re);
+static void dump_dwarf_pubnames(struct readelf *re);
+static void dump_dwarf_ranges(struct readelf *re);
+static void dump_dwarf_ranges_foreach(struct readelf *re, Dwarf_Die die,
+    Dwarf_Addr base);
+static void dump_dwarf_str(struct readelf *re);
+static void dump_eflags(struct readelf *re, uint64_t e_flags);
+static void dump_elf(struct readelf *re);
+static void dump_dyn_val(struct readelf *re, GElf_Dyn *dyn, uint32_t stab);
+static void dump_dynamic(struct readelf *re);
+static void dump_liblist(struct readelf *re);
+static void dump_mips_abiflags(struct readelf *re, struct section *s);
+static void dump_mips_attributes(struct readelf *re, uint8_t *p, uint8_t *pe);
+static void dump_mips_odk_reginfo(struct readelf *re, uint8_t *p, size_t sz);
+static void dump_mips_options(struct readelf *re, struct section *s);
+static void dump_mips_option_flags(const char *name, struct mips_option *opt,
+    uint64_t info);
+static void dump_mips_reginfo(struct readelf *re, struct section *s);
+static void dump_mips_specific_info(struct readelf *re);
+static void dump_notes(struct readelf *re);
+static void dump_notes_content(struct readelf *re, const char *buf, size_t sz,
+    off_t off);
+static void dump_svr4_hash(struct section *s);
+static void dump_svr4_hash64(struct readelf *re, struct section *s);
+static void dump_gnu_hash(struct readelf *re, struct section *s);
+static void dump_hash(struct readelf *re);
+static void dump_phdr(struct readelf *re);
+static void dump_ppc_attributes(uint8_t *p, uint8_t *pe);
+static void dump_section_groups(struct readelf *re);
+static void dump_symtab(struct readelf *re, int i);
+static void dump_symtabs(struct readelf *re);
+static uint8_t *dump_unknown_tag(uint64_t tag, uint8_t *p, uint8_t *pe);
+static void dump_ver(struct readelf *re);
+static void dump_verdef(struct readelf *re, int dump);
+static void dump_verneed(struct readelf *re, int dump);
+static void dump_versym(struct readelf *re);
+static const char *dwarf_reg(unsigned int mach, unsigned int reg);
+static const char *dwarf_regname(struct readelf *re, unsigned int num);
+static struct dumpop *find_dumpop(struct readelf *re, size_t si,
+    const char *sn, int op, int t);
+static int get_ent_count(struct section *s, int *ent_count);
+static int get_mips_register_size(uint8_t flag);
+static char *get_regoff_str(struct readelf *re, Dwarf_Half reg,
+    Dwarf_Addr off);
+static const char *get_string(struct readelf *re, int strtab, size_t off);
+static const char *get_symbol_name(struct readelf *re, int symtab, int i);
+static uint64_t get_symbol_value(struct readelf *re, int symtab, int i);
+static void load_sections(struct readelf *re);
+static const char *mips_abi_fp(uint64_t fp);
+static const char *note_type(const char *note_name, unsigned int et,
+    unsigned int nt);
+static const char *note_type_freebsd(unsigned int nt);
+static const char *note_type_freebsd_core(unsigned int nt);
+static const char *note_type_linux_core(unsigned int nt);
+static const char *note_type_gnu(unsigned int nt);
+static const char *note_type_netbsd(unsigned int nt);
+static const char *note_type_openbsd(unsigned int nt);
+static const char *note_type_unknown(unsigned int nt);
+static const char *note_type_xen(unsigned int nt);
+static const char *option_kind(uint8_t kind);
+static const char *phdr_type(unsigned int mach, unsigned int ptype);
+static const char *ppc_abi_fp(uint64_t fp);
+static const char *ppc_abi_vector(uint64_t vec);
+static void readelf_usage(int status);
+static void readelf_version(void);
+static void search_loclist_at(struct readelf *re, Dwarf_Die die,
+    Dwarf_Unsigned lowpc);
+static void search_ver(struct readelf *re);
+static const char *section_type(unsigned int mach, unsigned int stype);
+static void set_cu_context(struct readelf *re, Dwarf_Half psize,
+    Dwarf_Half osize, Dwarf_Half ver);
+static const char *st_bind(unsigned int sbind);
+static const char *st_shndx(unsigned int shndx);
+static const char *st_type(unsigned int mach, unsigned int os,
+    unsigned int stype);
+static const char *st_vis(unsigned int svis);
+static const char *top_tag(unsigned int tag);
+static void unload_sections(struct readelf *re);
+static uint64_t _read_lsb(Elf_Data *d, uint64_t *offsetp,
+    int bytes_to_read);
+static uint64_t _read_msb(Elf_Data *d, uint64_t *offsetp,
+    int bytes_to_read);
+static uint64_t _decode_lsb(uint8_t **data, int bytes_to_read);
+static uint64_t _decode_msb(uint8_t **data, int bytes_to_read);
+static int64_t _decode_sleb128(uint8_t **dp, uint8_t *dpe);
+static uint64_t _decode_uleb128(uint8_t **dp, uint8_t *dpe);
+
+static struct eflags_desc arm_eflags_desc[] = {
+	{EF_ARM_RELEXEC, "relocatable executable"},
+	{EF_ARM_HASENTRY, "has entry point"},
+	{EF_ARM_SYMSARESORTED, "sorted symbol tables"},
+	{EF_ARM_DYNSYMSUSESEGIDX, "dynamic symbols use segment index"},
+	{EF_ARM_MAPSYMSFIRST, "mapping symbols precede others"},
+	{EF_ARM_BE8, "BE8"},
+	{EF_ARM_LE8, "LE8"},
+	{EF_ARM_INTERWORK, "interworking enabled"},
+	{EF_ARM_APCS_26, "uses APCS/26"},
+	{EF_ARM_APCS_FLOAT, "uses APCS/float"},
+	{EF_ARM_PIC, "position independent"},
+	{EF_ARM_ALIGN8, "8 bit structure alignment"},
+	{EF_ARM_NEW_ABI, "uses new ABI"},
+	{EF_ARM_OLD_ABI, "uses old ABI"},
+	{EF_ARM_SOFT_FLOAT, "software FP"},
+	{EF_ARM_VFP_FLOAT, "VFP"},
+	{EF_ARM_MAVERICK_FLOAT, "Maverick FP"},
+	{0, NULL}
+};
+
+static struct eflags_desc mips_eflags_desc[] = {
+	{EF_MIPS_NOREORDER, "noreorder"},
+	{EF_MIPS_PIC, "pic"},
+	{EF_MIPS_CPIC, "cpic"},
+	{EF_MIPS_UCODE, "ugen_reserved"},
+	{EF_MIPS_ABI2, "abi2"},
+	{EF_MIPS_OPTIONS_FIRST, "odk first"},
+	{EF_MIPS_ARCH_ASE_MDMX, "mdmx"},
+	{EF_MIPS_ARCH_ASE_M16, "mips16"},
+	{0, NULL}
+};
+
+static struct eflags_desc powerpc_eflags_desc[] = {
+	{EF_PPC_EMB, "emb"},
+	{EF_PPC_RELOCATABLE, "relocatable"},
+	{EF_PPC_RELOCATABLE_LIB, "relocatable-lib"},
+	{0, NULL}
+};
+
+static struct eflags_desc sparc_eflags_desc[] = {
+	{EF_SPARC_32PLUS, "v8+"},
+	{EF_SPARC_SUN_US1, "ultrasparcI"},
+	{EF_SPARC_HAL_R1, "halr1"},
+	{EF_SPARC_SUN_US3, "ultrasparcIII"},
+	{0, NULL}
+};
+
+static const char *
+elf_osabi(unsigned int abi)
+{
+	static char s_abi[32];
+
+	switch(abi) {
+	case ELFOSABI_NONE: return "NONE";
+	case ELFOSABI_HPUX: return "HPUX";
+	case ELFOSABI_NETBSD: return "NetBSD";
+	case ELFOSABI_GNU: return "GNU";
+	case ELFOSABI_HURD: return "HURD";
+	case ELFOSABI_86OPEN: return "86OPEN";
+	case ELFOSABI_SOLARIS: return "Solaris";
+	case ELFOSABI_AIX: return "AIX";
+	case ELFOSABI_IRIX: return "IRIX";
+	case ELFOSABI_FREEBSD: return "FreeBSD";
+	case ELFOSABI_TRU64: return "TRU64";
+	case ELFOSABI_MODESTO: return "MODESTO";
+	case ELFOSABI_OPENBSD: return "OpenBSD";
+	case ELFOSABI_OPENVMS: return "OpenVMS";
+	case ELFOSABI_NSK: return "NSK";
+	case ELFOSABI_CLOUDABI: return "CloudABI";
+	case ELFOSABI_ARM_AEABI: return "ARM EABI";
+	case ELFOSABI_ARM: return "ARM";
+	case ELFOSABI_STANDALONE: return "StandAlone";
+	default:
+		snprintf(s_abi, sizeof(s_abi), "<unknown: %#x>", abi);
+		return (s_abi);
+	}
+};
+
+static const char *
+elf_machine(unsigned int mach)
+{
+	static char s_mach[32];
+
+	switch (mach) {
+	case EM_NONE: return "Unknown machine";
+	case EM_M32: return "AT&T WE32100";
+	case EM_SPARC: return "Sun SPARC";
+	case EM_386: return "Intel i386";
+	case EM_68K: return "Motorola 68000";
+	case EM_IAMCU: return "Intel MCU";
+	case EM_88K: return "Motorola 88000";
+	case EM_860: return "Intel i860";
+	case EM_MIPS: return "MIPS R3000 Big-Endian only";
+	case EM_S370: return "IBM System/370";
+	case EM_MIPS_RS3_LE: return "MIPS R3000 Little-Endian";
+	case EM_PARISC: return "HP PA-RISC";
+	case EM_VPP500: return "Fujitsu VPP500";
+	case EM_SPARC32PLUS: return "SPARC v8plus";
+	case EM_960: return "Intel 80960";
+	case EM_PPC: return "PowerPC 32-bit";
+	case EM_PPC64: return "PowerPC 64-bit";
+	case EM_S390: return "IBM System/390";
+	case EM_V800: return "NEC V800";
+	case EM_FR20: return "Fujitsu FR20";
+	case EM_RH32: return "TRW RH-32";
+	case EM_RCE: return "Motorola RCE";
+	case EM_ARM: return "ARM";
+	case EM_SH: return "Hitachi SH";
+	case EM_SPARCV9: return "SPARC v9 64-bit";
+	case EM_TRICORE: return "Siemens TriCore embedded processor";
+	case EM_ARC: return "Argonaut RISC Core";
+	case EM_H8_300: return "Hitachi H8/300";
+	case EM_H8_300H: return "Hitachi H8/300H";
+	case EM_H8S: return "Hitachi H8S";
+	case EM_H8_500: return "Hitachi H8/500";
+	case EM_IA_64: return "Intel IA-64 Processor";
+	case EM_MIPS_X: return "Stanford MIPS-X";
+	case EM_COLDFIRE: return "Motorola ColdFire";
+	case EM_68HC12: return "Motorola M68HC12";
+	case EM_MMA: return "Fujitsu MMA";
+	case EM_PCP: return "Siemens PCP";
+	case EM_NCPU: return "Sony nCPU";
+	case EM_NDR1: return "Denso NDR1 microprocessor";
+	case EM_STARCORE: return "Motorola Star*Core processor";
+	case EM_ME16: return "Toyota ME16 processor";
+	case EM_ST100: return "STMicroelectronics ST100 processor";
+	case EM_TINYJ: return "Advanced Logic Corp. TinyJ processor";
+	case EM_X86_64: return "Advanced Micro Devices x86-64";
+	case EM_PDSP: return "Sony DSP Processor";
+	case EM_FX66: return "Siemens FX66 microcontroller";
+	case EM_ST9PLUS: return "STMicroelectronics ST9+ 8/16 microcontroller";
+	case EM_ST7: return "STmicroelectronics ST7 8-bit microcontroller";
+	case EM_68HC16: return "Motorola MC68HC16 microcontroller";
+	case EM_68HC11: return "Motorola MC68HC11 microcontroller";
+	case EM_68HC08: return "Motorola MC68HC08 microcontroller";
+	case EM_68HC05: return "Motorola MC68HC05 microcontroller";
+	case EM_SVX: return "Silicon Graphics SVx";
+	case EM_ST19: return "STMicroelectronics ST19 8-bit mc";
+	case EM_VAX: return "Digital VAX";
+	case EM_CRIS: return "Axis Communications 32-bit embedded processor";
+	case EM_JAVELIN: return "Infineon Tech. 32bit embedded processor";
+	case EM_FIREPATH: return "Element 14 64-bit DSP Processor";
+	case EM_ZSP: return "LSI Logic 16-bit DSP Processor";
+	case EM_MMIX: return "Donald Knuth's educational 64-bit proc";
+	case EM_HUANY: return "Harvard University MI object files";
+	case EM_PRISM: return "SiTera Prism";
+	case EM_AVR: return "Atmel AVR 8-bit microcontroller";
+	case EM_FR30: return "Fujitsu FR30";
+	case EM_D10V: return "Mitsubishi D10V";
+	case EM_D30V: return "Mitsubishi D30V";
+	case EM_V850: return "NEC v850";
+	case EM_M32R: return "Mitsubishi M32R";
+	case EM_MN10300: return "Matsushita MN10300";
+	case EM_MN10200: return "Matsushita MN10200";
+	case EM_PJ: return "picoJava";
+	case EM_OPENRISC: return "OpenRISC 32-bit embedded processor";
+	case EM_ARC_A5: return "ARC Cores Tangent-A5";
+	case EM_XTENSA: return "Tensilica Xtensa Architecture";
+	case EM_VIDEOCORE: return "Alphamosaic VideoCore processor";
+	case EM_TMM_GPP: return "Thompson Multimedia General Purpose Processor";
+	case EM_NS32K: return "National Semiconductor 32000 series";
+	case EM_TPC: return "Tenor Network TPC processor";
+	case EM_SNP1K: return "Trebia SNP 1000 processor";
+	case EM_ST200: return "STMicroelectronics ST200 microcontroller";
+	case EM_IP2K: return "Ubicom IP2xxx microcontroller family";
+	case EM_MAX: return "MAX Processor";
+	case EM_CR: return "National Semiconductor CompactRISC microprocessor";
+	case EM_F2MC16: return "Fujitsu F2MC16";
+	case EM_MSP430: return "TI embedded microcontroller msp430";
+	case EM_BLACKFIN: return "Analog Devices Blackfin (DSP) processor";
+	case EM_SE_C33: return "S1C33 Family of Seiko Epson processors";
+	case EM_SEP: return "Sharp embedded microprocessor";
+	case EM_ARCA: return "Arca RISC Microprocessor";
+	case EM_UNICORE: return "Microprocessor series from PKU-Unity Ltd";
+	case EM_AARCH64: return "AArch64";
+	case EM_RISCV: return "RISC-V";
+	default:
+		snprintf(s_mach, sizeof(s_mach), "<unknown: %#x>", mach);
+		return (s_mach);
+	}
+
+}
+
+static const char *
+elf_class(unsigned int class)
+{
+	static char s_class[32];
+
+	switch (class) {
+	case ELFCLASSNONE: return "none";
+	case ELFCLASS32: return "ELF32";
+	case ELFCLASS64: return "ELF64";
+	default:
+		snprintf(s_class, sizeof(s_class), "<unknown: %#x>", class);
+		return (s_class);
+	}
+}
+
+static const char *
+elf_endian(unsigned int endian)
+{
+	static char s_endian[32];
+
+	switch (endian) {
+	case ELFDATANONE: return "none";
+	case ELFDATA2LSB: return "2's complement, little endian";
+	case ELFDATA2MSB: return "2's complement, big endian";
+	default:
+		snprintf(s_endian, sizeof(s_endian), "<unknown: %#x>", endian);
+		return (s_endian);
+	}
+}
+
+static const char *
+elf_type(unsigned int type)
+{
+	static char s_type[32];
+
+	switch (type) {
+	case ET_NONE: return "NONE (None)";
+	case ET_REL: return "REL (Relocatable file)";
+	case ET_EXEC: return "EXEC (Executable file)";
+	case ET_DYN: return "DYN (Shared object file)";
+	case ET_CORE: return "CORE (Core file)";
+	default:
+		if (type >= ET_LOPROC)
+			snprintf(s_type, sizeof(s_type), "<proc: %#x>", type);
+		else if (type >= ET_LOOS && type <= ET_HIOS)
+			snprintf(s_type, sizeof(s_type), "<os: %#x>", type);
+		else
+			snprintf(s_type, sizeof(s_type), "<unknown: %#x>",
+			    type);
+		return (s_type);
+	}
+}
+
+static const char *
+elf_ver(unsigned int ver)
+{
+	static char s_ver[32];
+
+	switch (ver) {
+	case EV_CURRENT: return "(current)";
+	case EV_NONE: return "(none)";
+	default:
+		snprintf(s_ver, sizeof(s_ver), "<unknown: %#x>",
+		    ver);
+		return (s_ver);
+	}
+}
+
+static const char *
+phdr_type(unsigned int mach, unsigned int ptype)
+{
+	static char s_ptype[32];
+
+	if (ptype >= PT_LOPROC && ptype <= PT_HIPROC) {
+		switch (mach) {
+		case EM_ARM:
+			switch (ptype) {
+			case PT_ARM_ARCHEXT: return "ARM_ARCHEXT";
+			case PT_ARM_EXIDX: return "ARM_EXIDX";
+			}
+			break;
+		}
+		snprintf(s_ptype, sizeof(s_ptype), "LOPROC+%#x",
+		    ptype - PT_LOPROC);
+		return (s_ptype);
+	}
+
+	switch (ptype) {
+	case PT_NULL: return "NULL";
+	case PT_LOAD: return "LOAD";
+	case PT_DYNAMIC: return "DYNAMIC";
+	case PT_INTERP: return "INTERP";
+	case PT_NOTE: return "NOTE";
+	case PT_SHLIB: return "SHLIB";
+	case PT_PHDR: return "PHDR";
+	case PT_TLS: return "TLS";
+	case PT_GNU_EH_FRAME: return "GNU_EH_FRAME";
+	case PT_GNU_STACK: return "GNU_STACK";
+	case PT_GNU_RELRO: return "GNU_RELRO";
+	default:
+		if (ptype >= PT_LOOS && ptype <= PT_HIOS)
+			snprintf(s_ptype, sizeof(s_ptype), "LOOS+%#x",
+			    ptype - PT_LOOS);
+		else
+			snprintf(s_ptype, sizeof(s_ptype), "<unknown: %#x>",
+			    ptype);
+		return (s_ptype);
+	}
+}
+
+static const char *
+section_type(unsigned int mach, unsigned int stype)
+{
+	static char s_stype[32];
+
+	if (stype >= SHT_LOPROC && stype <= SHT_HIPROC) {
+		switch (mach) {
+		case EM_ARM:
+			switch (stype) {
+			case SHT_ARM_EXIDX: return "ARM_EXIDX";
+			case SHT_ARM_PREEMPTMAP: return "ARM_PREEMPTMAP";
+			case SHT_ARM_ATTRIBUTES: return "ARM_ATTRIBUTES";
+			case SHT_ARM_DEBUGOVERLAY: return "ARM_DEBUGOVERLAY";
+			case SHT_ARM_OVERLAYSECTION: return "ARM_OVERLAYSECTION";
+			}
+			break;
+		case EM_X86_64:
+			switch (stype) {
+			case SHT_X86_64_UNWIND: return "X86_64_UNWIND";
+			default:
+				break;
+			}
+			break;
+		case EM_MIPS:
+		case EM_MIPS_RS3_LE:
+			switch (stype) {
+			case SHT_MIPS_LIBLIST: return "MIPS_LIBLIST";
+			case SHT_MIPS_MSYM: return "MIPS_MSYM";
+			case SHT_MIPS_CONFLICT: return "MIPS_CONFLICT";
+			case SHT_MIPS_GPTAB: return "MIPS_GPTAB";
+			case SHT_MIPS_UCODE: return "MIPS_UCODE";
+			case SHT_MIPS_DEBUG: return "MIPS_DEBUG";
+			case SHT_MIPS_REGINFO: return "MIPS_REGINFO";
+			case SHT_MIPS_PACKAGE: return "MIPS_PACKAGE";
+			case SHT_MIPS_PACKSYM: return "MIPS_PACKSYM";
+			case SHT_MIPS_RELD: return "MIPS_RELD";
+			case SHT_MIPS_IFACE: return "MIPS_IFACE";
+			case SHT_MIPS_CONTENT: return "MIPS_CONTENT";
+			case SHT_MIPS_OPTIONS: return "MIPS_OPTIONS";
+			case SHT_MIPS_DELTASYM: return "MIPS_DELTASYM";
+			case SHT_MIPS_DELTAINST: return "MIPS_DELTAINST";
+			case SHT_MIPS_DELTACLASS: return "MIPS_DELTACLASS";
+			case SHT_MIPS_DWARF: return "MIPS_DWARF";
+			case SHT_MIPS_DELTADECL: return "MIPS_DELTADECL";
+			case SHT_MIPS_SYMBOL_LIB: return "MIPS_SYMBOL_LIB";
+			case SHT_MIPS_EVENTS: return "MIPS_EVENTS";
+			case SHT_MIPS_TRANSLATE: return "MIPS_TRANSLATE";
+			case SHT_MIPS_PIXIE: return "MIPS_PIXIE";
+			case SHT_MIPS_XLATE: return "MIPS_XLATE";
+			case SHT_MIPS_XLATE_DEBUG: return "MIPS_XLATE_DEBUG";
+			case SHT_MIPS_WHIRL: return "MIPS_WHIRL";
+			case SHT_MIPS_EH_REGION: return "MIPS_EH_REGION";
+			case SHT_MIPS_XLATE_OLD: return "MIPS_XLATE_OLD";
+			case SHT_MIPS_PDR_EXCEPTION: return "MIPS_PDR_EXCEPTION";
+			case SHT_MIPS_ABIFLAGS: return "MIPS_ABIFLAGS";
+			default:
+				break;
+			}
+			break;
+		default:
+			break;
+		}
+
+		snprintf(s_stype, sizeof(s_stype), "LOPROC+%#x",
+		    stype - SHT_LOPROC);
+		return (s_stype);
+	}
+
+	switch (stype) {
+	case SHT_NULL: return "NULL";
+	case SHT_PROGBITS: return "PROGBITS";
+	case SHT_SYMTAB: return "SYMTAB";
+	case SHT_STRTAB: return "STRTAB";
+	case SHT_RELA: return "RELA";
+	case SHT_HASH: return "HASH";
+	case SHT_DYNAMIC: return "DYNAMIC";
+	case SHT_NOTE: return "NOTE";
+	case SHT_NOBITS: return "NOBITS";
+	case SHT_REL: return "REL";
+	case SHT_SHLIB: return "SHLIB";
+	case SHT_DYNSYM: return "DYNSYM";
+	case SHT_INIT_ARRAY: return "INIT_ARRAY";
+	case SHT_FINI_ARRAY: return "FINI_ARRAY";
+	case SHT_PREINIT_ARRAY: return "PREINIT_ARRAY";
+	case SHT_GROUP: return "GROUP";
+	case SHT_SYMTAB_SHNDX: return "SYMTAB_SHNDX";
+	case SHT_SUNW_dof: return "SUNW_dof";
+	case SHT_SUNW_cap: return "SUNW_cap";
+	case SHT_GNU_HASH: return "GNU_HASH";
+	case SHT_SUNW_ANNOTATE: return "SUNW_ANNOTATE";
+	case SHT_SUNW_DEBUGSTR: return "SUNW_DEBUGSTR";
+	case SHT_SUNW_DEBUG: return "SUNW_DEBUG";
+	case SHT_SUNW_move: return "SUNW_move";
+	case SHT_SUNW_COMDAT: return "SUNW_COMDAT";
+	case SHT_SUNW_syminfo: return "SUNW_syminfo";
+	case SHT_SUNW_verdef: return "SUNW_verdef";
+	case SHT_SUNW_verneed: return "SUNW_verneed";
+	case SHT_SUNW_versym: return "SUNW_versym";
+	default:
+		if (stype >= SHT_LOOS && stype <= SHT_HIOS)
+			snprintf(s_stype, sizeof(s_stype), "LOOS+%#x",
+			    stype - SHT_LOOS);
+		else if (stype >= SHT_LOUSER)
+			snprintf(s_stype, sizeof(s_stype), "LOUSER+%#x",
+			    stype - SHT_LOUSER);
+		else
+			snprintf(s_stype, sizeof(s_stype), "<unknown: %#x>",
+			    stype);
+		return (s_stype);
+	}
+}
+
+static const char *
+dt_type(unsigned int mach, unsigned int dtype)
+{
+	static char s_dtype[32];
+
+	switch (dtype) {
+	case DT_NULL: return "NULL";
+	case DT_NEEDED: return "NEEDED";
+	case DT_PLTRELSZ: return "PLTRELSZ";
+	case DT_PLTGOT: return "PLTGOT";
+	case DT_HASH: return "HASH";
+	case DT_STRTAB: return "STRTAB";
+	case DT_SYMTAB: return "SYMTAB";
+	case DT_RELA: return "RELA";
+	case DT_RELASZ: return "RELASZ";
+	case DT_RELAENT: return "RELAENT";
+	case DT_STRSZ: return "STRSZ";
+	case DT_SYMENT: return "SYMENT";
+	case DT_INIT: return "INIT";
+	case DT_FINI: return "FINI";
+	case DT_SONAME: return "SONAME";
+	case DT_RPATH: return "RPATH";
+	case DT_SYMBOLIC: return "SYMBOLIC";
+	case DT_REL: return "REL";
+	case DT_RELSZ: return "RELSZ";
+	case DT_RELENT: return "RELENT";
+	case DT_PLTREL: return "PLTREL";
+	case DT_DEBUG: return "DEBUG";
+	case DT_TEXTREL: return "TEXTREL";
+	case DT_JMPREL: return "JMPREL";
+	case DT_BIND_NOW: return "BIND_NOW";
+	case DT_INIT_ARRAY: return "INIT_ARRAY";
+	case DT_FINI_ARRAY: return "FINI_ARRAY";
+	case DT_INIT_ARRAYSZ: return "INIT_ARRAYSZ";
+	case DT_FINI_ARRAYSZ: return "FINI_ARRAYSZ";
+	case DT_RUNPATH: return "RUNPATH";
+	case DT_FLAGS: return "FLAGS";
+	case DT_PREINIT_ARRAY: return "PREINIT_ARRAY";
+	case DT_PREINIT_ARRAYSZ: return "PREINIT_ARRAYSZ";
+	case DT_MAXPOSTAGS: return "MAXPOSTAGS";
+	case DT_SUNW_AUXILIARY: return "SUNW_AUXILIARY";
+	case DT_SUNW_RTLDINF: return "SUNW_RTLDINF";
+	case DT_SUNW_FILTER: return "SUNW_FILTER";
+	case DT_SUNW_CAP: return "SUNW_CAP";
+	case DT_SUNW_ASLR: return "SUNW_ASLR";
+	case DT_CHECKSUM: return "CHECKSUM";
+	case DT_PLTPADSZ: return "PLTPADSZ";
+	case DT_MOVEENT: return "MOVEENT";
+	case DT_MOVESZ: return "MOVESZ";
+	case DT_FEATURE: return "FEATURE";
+	case DT_POSFLAG_1: return "POSFLAG_1";
+	case DT_SYMINSZ: return "SYMINSZ";
+	case DT_SYMINENT: return "SYMINENT";
+	case DT_GNU_HASH: return "GNU_HASH";
+	case DT_TLSDESC_PLT: return "DT_TLSDESC_PLT";
+	case DT_TLSDESC_GOT: return "DT_TLSDESC_GOT";
+	case DT_GNU_CONFLICT: return "GNU_CONFLICT";
+	case DT_GNU_LIBLIST: return "GNU_LIBLIST";
+	case DT_CONFIG: return "CONFIG";
+	case DT_DEPAUDIT: return "DEPAUDIT";
+	case DT_AUDIT: return "AUDIT";
+	case DT_PLTPAD: return "PLTPAD";
+	case DT_MOVETAB: return "MOVETAB";
+	case DT_SYMINFO: return "SYMINFO";
+	case DT_VERSYM: return "VERSYM";
+	case DT_RELACOUNT: return "RELACOUNT";
+	case DT_RELCOUNT: return "RELCOUNT";
+	case DT_FLAGS_1: return "FLAGS_1";
+	case DT_VERDEF: return "VERDEF";
+	case DT_VERDEFNUM: return "VERDEFNUM";
+	case DT_VERNEED: return "VERNEED";
+	case DT_VERNEEDNUM: return "VERNEEDNUM";
+	case DT_AUXILIARY: return "AUXILIARY";
+	case DT_USED: return "USED";
+	case DT_FILTER: return "FILTER";
+	case DT_GNU_PRELINKED: return "GNU_PRELINKED";
+	case DT_GNU_CONFLICTSZ: return "GNU_CONFLICTSZ";
+	case DT_GNU_LIBLISTSZ: return "GNU_LIBLISTSZ";
+	}
+
+	if (dtype >= DT_LOPROC && dtype <= DT_HIPROC) {
+		switch (mach) {
+		case EM_ARM:
+			switch (dtype) {
+			case DT_ARM_SYMTABSZ:
+				return "ARM_SYMTABSZ";
+			default:
+				break;
+			}
+			break;
+		case EM_MIPS:
+		case EM_MIPS_RS3_LE:
+			switch (dtype) {
+			case DT_MIPS_RLD_VERSION:
+				return "MIPS_RLD_VERSION";
+			case DT_MIPS_TIME_STAMP:
+				return "MIPS_TIME_STAMP";
+			case DT_MIPS_ICHECKSUM:
+				return "MIPS_ICHECKSUM";
+			case DT_MIPS_IVERSION:
+				return "MIPS_IVERSION";
+			case DT_MIPS_FLAGS:
+				return "MIPS_FLAGS";
+			case DT_MIPS_BASE_ADDRESS:
+				return "MIPS_BASE_ADDRESS";
+			case DT_MIPS_CONFLICT:
+				return "MIPS_CONFLICT";
+			case DT_MIPS_LIBLIST:
+				return "MIPS_LIBLIST";
+			case DT_MIPS_LOCAL_GOTNO:
+				return "MIPS_LOCAL_GOTNO";
+			case DT_MIPS_CONFLICTNO:
+				return "MIPS_CONFLICTNO";
+			case DT_MIPS_LIBLISTNO:
+				return "MIPS_LIBLISTNO";
+			case DT_MIPS_SYMTABNO:
+				return "MIPS_SYMTABNO";
+			case DT_MIPS_UNREFEXTNO:
+				return "MIPS_UNREFEXTNO";
+			case DT_MIPS_GOTSYM:
+				return "MIPS_GOTSYM";
+			case DT_MIPS_HIPAGENO:
+				return "MIPS_HIPAGENO";
+			case DT_MIPS_RLD_MAP:
+				return "MIPS_RLD_MAP";
+			case DT_MIPS_DELTA_CLASS:
+				return "MIPS_DELTA_CLASS";
+			case DT_MIPS_DELTA_CLASS_NO:
+				return "MIPS_DELTA_CLASS_NO";
+			case DT_MIPS_DELTA_INSTANCE:
+				return "MIPS_DELTA_INSTANCE";
+			case DT_MIPS_DELTA_INSTANCE_NO:
+				return "MIPS_DELTA_INSTANCE_NO";
+			case DT_MIPS_DELTA_RELOC:
+				return "MIPS_DELTA_RELOC";
+			case DT_MIPS_DELTA_RELOC_NO:
+				return "MIPS_DELTA_RELOC_NO";
+			case DT_MIPS_DELTA_SYM:
+				return "MIPS_DELTA_SYM";
+			case DT_MIPS_DELTA_SYM_NO:
+				return "MIPS_DELTA_SYM_NO";
+			case DT_MIPS_DELTA_CLASSSYM:
+				return "MIPS_DELTA_CLASSSYM";
+			case DT_MIPS_DELTA_CLASSSYM_NO:
+				return "MIPS_DELTA_CLASSSYM_NO";
+			case DT_MIPS_CXX_FLAGS:
+				return "MIPS_CXX_FLAGS";
+			case DT_MIPS_PIXIE_INIT:
+				return "MIPS_PIXIE_INIT";
+			case DT_MIPS_SYMBOL_LIB:
+				return "MIPS_SYMBOL_LIB";
+			case DT_MIPS_LOCALPAGE_GOTIDX:
+				return "MIPS_LOCALPAGE_GOTIDX";
+			case DT_MIPS_LOCAL_GOTIDX:
+				return "MIPS_LOCAL_GOTIDX";
+			case DT_MIPS_HIDDEN_GOTIDX:
+				return "MIPS_HIDDEN_GOTIDX";
+			case DT_MIPS_PROTECTED_GOTIDX:
+				return "MIPS_PROTECTED_GOTIDX";
+			case DT_MIPS_OPTIONS:
+				return "MIPS_OPTIONS";
+			case DT_MIPS_INTERFACE:
+				return "MIPS_INTERFACE";
+			case DT_MIPS_DYNSTR_ALIGN:
+				return "MIPS_DYNSTR_ALIGN";
+			case DT_MIPS_INTERFACE_SIZE:
+				return "MIPS_INTERFACE_SIZE";
+			case DT_MIPS_RLD_TEXT_RESOLVE_ADDR:
+				return "MIPS_RLD_TEXT_RESOLVE_ADDR";
+			case DT_MIPS_PERF_SUFFIX:
+				return "MIPS_PERF_SUFFIX";
+			case DT_MIPS_COMPACT_SIZE:
+				return "MIPS_COMPACT_SIZE";
+			case DT_MIPS_GP_VALUE:
+				return "MIPS_GP_VALUE";
+			case DT_MIPS_AUX_DYNAMIC:
+				return "MIPS_AUX_DYNAMIC";
+			case DT_MIPS_PLTGOT:
+				return "MIPS_PLTGOT";
+			case DT_MIPS_RLD_OBJ_UPDATE:
+				return "MIPS_RLD_OBJ_UPDATE";
+			case DT_MIPS_RWPLT:
+				return "MIPS_RWPLT";
+			default:
+				break;
+			}
+			break;
+		case EM_SPARC:
+		case EM_SPARC32PLUS:
+		case EM_SPARCV9:
+			switch (dtype) {
+			case DT_SPARC_REGISTER:
+				return "DT_SPARC_REGISTER";
+			default:
+				break;
+			}
+			break;
+		default:
+			break;
+		}
+	}
+
+	snprintf(s_dtype, sizeof(s_dtype), "<unknown: %#x>", dtype);
+	return (s_dtype);
+}
+
+static const char *
+st_bind(unsigned int sbind)
+{
+	static char s_sbind[32];
+
+	switch (sbind) {
+	case STB_LOCAL: return "LOCAL";
+	case STB_GLOBAL: return "GLOBAL";
+	case STB_WEAK: return "WEAK";
+	case STB_GNU_UNIQUE: return "UNIQUE";
+	default:
+		if (sbind >= STB_LOOS && sbind <= STB_HIOS)
+			return "OS";
+		else if (sbind >= STB_LOPROC && sbind <= STB_HIPROC)
+			return "PROC";
+		else
+			snprintf(s_sbind, sizeof(s_sbind), "<unknown: %#x>",
+			    sbind);
+		return (s_sbind);
+	}
+}
+
+static const char *
+st_type(unsigned int mach, unsigned int os, unsigned int stype)
+{
+	static char s_stype[32];
+
+	switch (stype) {
+	case STT_NOTYPE: return "NOTYPE";
+	case STT_OBJECT: return "OBJECT";
+	case STT_FUNC: return "FUNC";
+	case STT_SECTION: return "SECTION";
+	case STT_FILE: return "FILE";
+	case STT_COMMON: return "COMMON";
+	case STT_TLS: return "TLS";
+	default:
+		if (stype >= STT_LOOS && stype <= STT_HIOS) {
+			if ((os == ELFOSABI_GNU || os == ELFOSABI_FREEBSD) &&
+			    stype == STT_GNU_IFUNC)
+				return "IFUNC";
+			snprintf(s_stype, sizeof(s_stype), "OS+%#x",
+			    stype - STT_LOOS);
+		} else if (stype >= STT_LOPROC && stype <= STT_HIPROC) {
+			if (mach == EM_SPARCV9 && stype == STT_SPARC_REGISTER)
+				return "REGISTER";
+			snprintf(s_stype, sizeof(s_stype), "PROC+%#x",
+			    stype - STT_LOPROC);
+		} else
+			snprintf(s_stype, sizeof(s_stype), "<unknown: %#x>",
+			    stype);
+		return (s_stype);
+	}
+}
+
+static const char *
+st_vis(unsigned int svis)
+{
+	static char s_svis[32];
+
+	switch(svis) {
+	case STV_DEFAULT: return "DEFAULT";
+	case STV_INTERNAL: return "INTERNAL";
+	case STV_HIDDEN: return "HIDDEN";
+	case STV_PROTECTED: return "PROTECTED";
+	default:
+		snprintf(s_svis, sizeof(s_svis), "<unknown: %#x>", svis);
+		return (s_svis);
+	}
+}
+
+static const char *
+st_shndx(unsigned int shndx)
+{
+	static char s_shndx[32];
+
+	switch (shndx) {
+	case SHN_UNDEF: return "UND";
+	case SHN_ABS: return "ABS";
+	case SHN_COMMON: return "COM";
+	default:
+		if (shndx >= SHN_LOPROC && shndx <= SHN_HIPROC)
+			return "PRC";
+		else if (shndx >= SHN_LOOS && shndx <= SHN_HIOS)
+			return "OS";
+		else
+			snprintf(s_shndx, sizeof(s_shndx), "%u", shndx);
+		return (s_shndx);
+	}
+}
+
+static struct {
+	const char *ln;
+	char sn;
+	int value;
+} section_flag[] = {
+	{"WRITE", 'W', SHF_WRITE},
+	{"ALLOC", 'A', SHF_ALLOC},
+	{"EXEC", 'X', SHF_EXECINSTR},
+	{"MERGE", 'M', SHF_MERGE},
+	{"STRINGS", 'S', SHF_STRINGS},
+	{"INFO LINK", 'I', SHF_INFO_LINK},
+	{"OS NONCONF", 'O', SHF_OS_NONCONFORMING},
+	{"GROUP", 'G', SHF_GROUP},
+	{"TLS", 'T', SHF_TLS},
+	{"COMPRESSED", 'C', SHF_COMPRESSED},
+	{NULL, 0, 0}
+};
+
+static const char *
+note_type(const char *name, unsigned int et, unsigned int nt)
+{
+	if ((strcmp(name, "CORE") == 0 || strcmp(name, "LINUX") == 0) &&
+	    et == ET_CORE)
+		return note_type_linux_core(nt);
+	else if (strcmp(name, "FreeBSD") == 0)
+		if (et == ET_CORE)
+			return note_type_freebsd_core(nt);
+		else
+			return note_type_freebsd(nt);
+	else if (strcmp(name, "GNU") == 0 && et != ET_CORE)
+		return note_type_gnu(nt);
+	else if (strcmp(name, "NetBSD") == 0 && et != ET_CORE)
+		return note_type_netbsd(nt);
+	else if (strcmp(name, "OpenBSD") == 0 && et != ET_CORE)
+		return note_type_openbsd(nt);
+	else if (strcmp(name, "Xen") == 0 && et != ET_CORE)
+		return note_type_xen(nt);
+	return note_type_unknown(nt);
+}
+
+static const char *
+note_type_freebsd(unsigned int nt)
+{
+	switch (nt) {
+	case 1: return "NT_FREEBSD_ABI_TAG";
+	case 2: return "NT_FREEBSD_NOINIT_TAG";
+	case 3: return "NT_FREEBSD_ARCH_TAG";
+	case 4: return "NT_FREEBSD_FEATURE_CTL";
+	default: return (note_type_unknown(nt));
+	}
+}
+
+static const char *
+note_type_freebsd_core(unsigned int nt)
+{
+	switch (nt) {
+	case 1: return "NT_PRSTATUS";
+	case 2: return "NT_FPREGSET";
+	case 3: return "NT_PRPSINFO";
+	case 7: return "NT_THRMISC";
+	case 8: return "NT_PROCSTAT_PROC";
+	case 9: return "NT_PROCSTAT_FILES";
+	case 10: return "NT_PROCSTAT_VMMAP";
+	case 11: return "NT_PROCSTAT_GROUPS";
+	case 12: return "NT_PROCSTAT_UMASK";
+	case 13: return "NT_PROCSTAT_RLIMIT";
+	case 14: return "NT_PROCSTAT_OSREL";
+	case 15: return "NT_PROCSTAT_PSSTRINGS";
+	case 16: return "NT_PROCSTAT_AUXV";
+	case 17: return "NT_PTLWPINFO";
+	case 0x202: return "NT_X86_XSTATE (x86 XSAVE extended state)";
+	case 0x400: return "NT_ARM_VFP (arm VFP registers)";
+	default: return (note_type_unknown(nt));
+	}
+}
+
+static const char *
+note_type_linux_core(unsigned int nt)
+{
+	switch (nt) {
+	case 1: return "NT_PRSTATUS (Process status)";
+	case 2: return "NT_FPREGSET (Floating point information)";
+	case 3: return "NT_PRPSINFO (Process information)";
+	case 4: return "NT_TASKSTRUCT (Task structure)";
+	case 6: return "NT_AUXV (Auxiliary vector)";
+	case 10: return "NT_PSTATUS (Linux process status)";
+	case 12: return "NT_FPREGS (Linux floating point regset)";
+	case 13: return "NT_PSINFO (Linux process information)";
+	case 16: return "NT_LWPSTATUS (Linux lwpstatus_t type)";
+	case 17: return "NT_LWPSINFO (Linux lwpinfo_t type)";
+	case 18: return "NT_WIN32PSTATUS (win32_pstatus structure)";
+	case 0x100: return "NT_PPC_VMX (ppc Altivec registers)";
+	case 0x102: return "NT_PPC_VSX (ppc VSX registers)";
+	case 0x202: return "NT_X86_XSTATE (x86 XSAVE extended state)";
+	case 0x300: return "NT_S390_HIGH_GPRS (s390 upper register halves)";
+	case 0x301: return "NT_S390_TIMER (s390 timer register)";
+	case 0x302: return "NT_S390_TODCMP (s390 TOD comparator register)";
+	case 0x303: return "NT_S390_TODPREG (s390 TOD programmable register)";
+	case 0x304: return "NT_S390_CTRS (s390 control registers)";
+	case 0x305: return "NT_S390_PREFIX (s390 prefix register)";
+	case 0x400: return "NT_ARM_VFP (arm VFP registers)";
+	case 0x46494c45UL: return "NT_FILE (mapped files)";
+	case 0x46E62B7FUL: return "NT_PRXFPREG (Linux user_xfpregs structure)";
+	case 0x53494749UL: return "NT_SIGINFO (siginfo_t data)";
+	default: return (note_type_unknown(nt));
+	}
+}
+
+static const char *
+note_type_gnu(unsigned int nt)
+{
+	switch (nt) {
+	case 1: return "NT_GNU_ABI_TAG";
+	case 2: return "NT_GNU_HWCAP (Hardware capabilities)";
+	case 3: return "NT_GNU_BUILD_ID (Build id set by ld(1))";
+	case 4: return "NT_GNU_GOLD_VERSION (GNU gold version)";
+	case 5: return "NT_GNU_PROPERTY_TYPE_0";
+	default: return (note_type_unknown(nt));
+	}
+}
+
+static const char *
+note_type_netbsd(unsigned int nt)
+{
+	switch (nt) {
+	case 1: return "NT_NETBSD_IDENT";
+	default: return (note_type_unknown(nt));
+	}
+}
+
+static const char *
+note_type_openbsd(unsigned int nt)
+{
+	switch (nt) {
+	case 1: return "NT_OPENBSD_IDENT";
+	default: return (note_type_unknown(nt));
+	}
+}
+
+static const char *
+note_type_unknown(unsigned int nt)
+{
+	static char s_nt[32];
+
+	snprintf(s_nt, sizeof(s_nt),
+	    nt >= 0x100 ? "<unknown: 0x%x>" : "<unknown: %u>", nt);
+	return (s_nt);
+}
+
+static const char *
+note_type_xen(unsigned int nt)
+{
+	switch (nt) {
+	case 0: return "XEN_ELFNOTE_INFO";
+	case 1: return "XEN_ELFNOTE_ENTRY";
+	case 2: return "XEN_ELFNOTE_HYPERCALL_PAGE";
+	case 3: return "XEN_ELFNOTE_VIRT_BASE";
+	case 4: return "XEN_ELFNOTE_PADDR_OFFSET";
+	case 5: return "XEN_ELFNOTE_XEN_VERSION";
+	case 6: return "XEN_ELFNOTE_GUEST_OS";
+	case 7: return "XEN_ELFNOTE_GUEST_VERSION";
+	case 8: return "XEN_ELFNOTE_LOADER";
+	case 9: return "XEN_ELFNOTE_PAE_MODE";
+	case 10: return "XEN_ELFNOTE_FEATURES";
+	case 11: return "XEN_ELFNOTE_BSD_SYMTAB";
+	case 12: return "XEN_ELFNOTE_HV_START_LOW";
+	case 13: return "XEN_ELFNOTE_L1_MFN_VALID";
+	case 14: return "XEN_ELFNOTE_SUSPEND_CANCEL";
+	case 15: return "XEN_ELFNOTE_INIT_P2M";
+	case 16: return "XEN_ELFNOTE_MOD_START_PFN";
+	case 17: return "XEN_ELFNOTE_SUPPORTED_FEATURES";
+	default: return (note_type_unknown(nt));
+	}
+}
+
+static struct {
+	const char *name;
+	int value;
+} l_flag[] = {
+	{"EXACT_MATCH", LL_EXACT_MATCH},
+	{"IGNORE_INT_VER", LL_IGNORE_INT_VER},
+	{"REQUIRE_MINOR", LL_REQUIRE_MINOR},
+	{"EXPORTS", LL_EXPORTS},
+	{"DELAY_LOAD", LL_DELAY_LOAD},
+	{"DELTA", LL_DELTA},
+	{NULL, 0}
+};
+
+static struct mips_option mips_exceptions_option[] = {
+	{OEX_PAGE0, "PAGE0"},
+	{OEX_SMM, "SMM"},
+	{OEX_PRECISEFP, "PRECISEFP"},
+	{OEX_DISMISS, "DISMISS"},
+	{0, NULL}
+};
+
+static struct mips_option mips_pad_option[] = {
+	{OPAD_PREFIX, "PREFIX"},
+	{OPAD_POSTFIX, "POSTFIX"},
+	{OPAD_SYMBOL, "SYMBOL"},
+	{0, NULL}
+};
+
+static struct mips_option mips_hwpatch_option[] = {
+	{OHW_R4KEOP, "R4KEOP"},
+	{OHW_R8KPFETCH, "R8KPFETCH"},
+	{OHW_R5KEOP, "R5KEOP"},
+	{OHW_R5KCVTL, "R5KCVTL"},
+	{0, NULL}
+};
+
+static struct mips_option mips_hwa_option[] = {
+	{OHWA0_R4KEOP_CHECKED, "R4KEOP_CHECKED"},
+	{OHWA0_R4KEOP_CLEAN, "R4KEOP_CLEAN"},
+	{0, NULL}
+};
+
+static struct mips_option mips_hwo_option[] = {
+	{OHWO0_FIXADE, "FIXADE"},
+	{0, NULL}
+};
+
+static const char *
+option_kind(uint8_t kind)
+{
+	static char s_kind[32];
+
+	switch (kind) {
+	case ODK_NULL: return "NULL";
+	case ODK_REGINFO: return "REGINFO";
+	case ODK_EXCEPTIONS: return "EXCEPTIONS";
+	case ODK_PAD: return "PAD";
+	case ODK_HWPATCH: return "HWPATCH";
+	case ODK_FILL: return "FILL";
+	case ODK_TAGS: return "TAGS";
+	case ODK_HWAND: return "HWAND";
+	case ODK_HWOR: return "HWOR";
+	case ODK_GP_GROUP: return "GP_GROUP";
+	case ODK_IDENT: return "IDENT";
+	default:
+		snprintf(s_kind, sizeof(s_kind), "<unknown: %u>", kind);
+		return (s_kind);
+	}
+}
+
+static const char *
+top_tag(unsigned int tag)
+{
+	static char s_top_tag[32];
+
+	switch (tag) {
+	case 1: return "File Attributes";
+	case 2: return "Section Attributes";
+	case 3: return "Symbol Attributes";
+	default:
+		snprintf(s_top_tag, sizeof(s_top_tag), "Unknown tag: %u", tag);
+		return (s_top_tag);
+	}
+}
+
+static const char *
+aeabi_cpu_arch(uint64_t arch)
+{
+	static char s_cpu_arch[32];
+
+	switch (arch) {
+	case 0: return "Pre-V4";
+	case 1: return "ARM v4";
+	case 2: return "ARM v4T";
+	case 3: return "ARM v5T";
+	case 4: return "ARM v5TE";
+	case 5: return "ARM v5TEJ";
+	case 6: return "ARM v6";
+	case 7: return "ARM v6KZ";
+	case 8: return "ARM v6T2";
+	case 9: return "ARM v6K";
+	case 10: return "ARM v7";
+	case 11: return "ARM v6-M";
+	case 12: return "ARM v6S-M";
+	case 13: return "ARM v7E-M";
+	default:
+		snprintf(s_cpu_arch, sizeof(s_cpu_arch),
+		    "Unknown (%ju)", (uintmax_t) arch);
+		return (s_cpu_arch);
+	}
+}
+
+static const char *
+aeabi_cpu_arch_profile(uint64_t pf)
+{
+	static char s_arch_profile[32];
+
+	switch (pf) {
+	case 0:
+		return "Not applicable";
+	case 0x41:		/* 'A' */
+		return "Application Profile";
+	case 0x52:		/* 'R' */
+		return "Real-Time Profile";
+	case 0x4D:		/* 'M' */
+		return "Microcontroller Profile";
+	case 0x53:		/* 'S' */
+		return "Application or Real-Time Profile";
+	default:
+		snprintf(s_arch_profile, sizeof(s_arch_profile),
+		    "Unknown (%ju)\n", (uintmax_t) pf);
+		return (s_arch_profile);
+	}
+}
+
+static const char *
+aeabi_arm_isa(uint64_t ai)
+{
+	static char s_ai[32];
+
+	switch (ai) {
+	case 0: return "No";
+	case 1: return "Yes";
+	default:
+		snprintf(s_ai, sizeof(s_ai), "Unknown (%ju)\n",
+		    (uintmax_t) ai);
+		return (s_ai);
+	}
+}
+
+static const char *
+aeabi_thumb_isa(uint64_t ti)
+{
+	static char s_ti[32];
+
+	switch (ti) {
+	case 0: return "No";
+	case 1: return "16-bit Thumb";
+	case 2: return "32-bit Thumb";
+	default:
+		snprintf(s_ti, sizeof(s_ti), "Unknown (%ju)\n",
+		    (uintmax_t) ti);
+		return (s_ti);
+	}
+}
+
+static const char *
+aeabi_fp_arch(uint64_t fp)
+{
+	static char s_fp_arch[32];
+
+	switch (fp) {
+	case 0: return "No";
+	case 1: return "VFPv1";
+	case 2: return "VFPv2";
+	case 3: return "VFPv3";
+	case 4: return "VFPv3-D16";
+	case 5: return "VFPv4";
+	case 6: return "VFPv4-D16";
+	default:
+		snprintf(s_fp_arch, sizeof(s_fp_arch), "Unknown (%ju)",
+		    (uintmax_t) fp);
+		return (s_fp_arch);
+	}
+}
+
+static const char *
+aeabi_wmmx_arch(uint64_t wmmx)
+{
+	static char s_wmmx[32];
+
+	switch (wmmx) {
+	case 0: return "No";
+	case 1: return "WMMXv1";
+	case 2: return "WMMXv2";
+	default:
+		snprintf(s_wmmx, sizeof(s_wmmx), "Unknown (%ju)",
+		    (uintmax_t) wmmx);
+		return (s_wmmx);
+	}
+}
+
+static const char *
+aeabi_adv_simd_arch(uint64_t simd)
+{
+	static char s_simd[32];
+
+	switch (simd) {
+	case 0: return "No";
+	case 1: return "NEONv1";
+	case 2: return "NEONv2";
+	default:
+		snprintf(s_simd, sizeof(s_simd), "Unknown (%ju)",
+		    (uintmax_t) simd);
+		return (s_simd);
+	}
+}
+
+static const char *
+aeabi_pcs_config(uint64_t pcs)
+{
+	static char s_pcs[32];
+
+	switch (pcs) {
+	case 0: return "None";
+	case 1: return "Bare platform";
+	case 2: return "Linux";
+	case 3: return "Linux DSO";
+	case 4: return "Palm OS 2004";
+	case 5: return "Palm OS (future)";
+	case 6: return "Symbian OS 2004";
+	case 7: return "Symbian OS (future)";
+	default:
+		snprintf(s_pcs, sizeof(s_pcs), "Unknown (%ju)",
+		    (uintmax_t) pcs);
+		return (s_pcs);
+	}
+}
+
+static const char *
+aeabi_pcs_r9(uint64_t r9)
+{
+	static char s_r9[32];
+
+	switch (r9) {
+	case 0: return "V6";
+	case 1: return "SB";
+	case 2: return "TLS pointer";
+	case 3: return "Unused";
+	default:
+		snprintf(s_r9, sizeof(s_r9), "Unknown (%ju)", (uintmax_t) r9);
+		return (s_r9);
+	}
+}
+
+static const char *
+aeabi_pcs_rw(uint64_t rw)
+{
+	static char s_rw[32];
+
+	switch (rw) {
+	case 0: return "Absolute";
+	case 1: return "PC-relative";
+	case 2: return "SB-relative";
+	case 3: return "None";
+	default:
+		snprintf(s_rw, sizeof(s_rw), "Unknown (%ju)", (uintmax_t) rw);
+		return (s_rw);
+	}
+}
+
+static const char *
+aeabi_pcs_ro(uint64_t ro)
+{
+	static char s_ro[32];
+
+	switch (ro) {
+	case 0: return "Absolute";
+	case 1: return "PC-relative";
+	case 2: return "None";
+	default:
+		snprintf(s_ro, sizeof(s_ro), "Unknown (%ju)", (uintmax_t) ro);
+		return (s_ro);
+	}
+}
+
+static const char *
+aeabi_pcs_got(uint64_t got)
+{
+	static char s_got[32];
+
+	switch (got) {
+	case 0: return "None";
+	case 1: return "direct";
+	case 2: return "indirect via GOT";
+	default:
+		snprintf(s_got, sizeof(s_got), "Unknown (%ju)",
+		    (uintmax_t) got);
+		return (s_got);
+	}
+}
+
+static const char *
+aeabi_pcs_wchar_t(uint64_t wt)
+{
+	static char s_wt[32];
+
+	switch (wt) {
+	case 0: return "None";
+	case 2: return "wchar_t size 2";
+	case 4: return "wchar_t size 4";
+	default:
+		snprintf(s_wt, sizeof(s_wt), "Unknown (%ju)", (uintmax_t) wt);
+		return (s_wt);
+	}
+}
+
+static const char *
+aeabi_enum_size(uint64_t es)
+{
+	static char s_es[32];
+
+	switch (es) {
+	case 0: return "None";
+	case 1: return "smallest";
+	case 2: return "32-bit";
+	case 3: return "visible 32-bit";
+	default:
+		snprintf(s_es, sizeof(s_es), "Unknown (%ju)", (uintmax_t) es);
+		return (s_es);
+	}
+}
+
+static const char *
+aeabi_align_needed(uint64_t an)
+{
+	static char s_align_n[64];
+
+	switch (an) {
+	case 0: return "No";
+	case 1: return "8-byte align";
+	case 2: return "4-byte align";
+	case 3: return "Reserved";
+	default:
+		if (an >= 4 && an <= 12)
+			snprintf(s_align_n, sizeof(s_align_n), "8-byte align"
+			    " and up to 2^%ju-byte extended align",
+			    (uintmax_t) an);
+		else
+			snprintf(s_align_n, sizeof(s_align_n), "Unknown (%ju)",
+			    (uintmax_t) an);
+		return (s_align_n);
+	}
+}
+
+static const char *
+aeabi_align_preserved(uint64_t ap)
+{
+	static char s_align_p[128];
+
+	switch (ap) {
+	case 0: return "No";
+	case 1: return "8-byte align";
+	case 2: return "8-byte align and SP % 8 == 0";
+	case 3: return "Reserved";
+	default:
+		if (ap >= 4 && ap <= 12)
+			snprintf(s_align_p, sizeof(s_align_p), "8-byte align"
+			    " and SP %% 8 == 0 and up to 2^%ju-byte extended"
+			    " align", (uintmax_t) ap);
+		else
+			snprintf(s_align_p, sizeof(s_align_p), "Unknown (%ju)",
+			    (uintmax_t) ap);
+		return (s_align_p);
+	}
+}
+
+static const char *
+aeabi_fp_rounding(uint64_t fr)
+{
+	static char s_fp_r[32];
+
+	switch (fr) {
+	case 0: return "Unused";
+	case 1: return "Needed";
+	default:
+		snprintf(s_fp_r, sizeof(s_fp_r), "Unknown (%ju)",
+		    (uintmax_t) fr);
+		return (s_fp_r);
+	}
+}
+
+static const char *
+aeabi_fp_denormal(uint64_t fd)
+{
+	static char s_fp_d[32];
+
+	switch (fd) {
+	case 0: return "Unused";
+	case 1: return "Needed";
+	case 2: return "Sign Only";
+	default:
+		snprintf(s_fp_d, sizeof(s_fp_d), "Unknown (%ju)",
+		    (uintmax_t) fd);
+		return (s_fp_d);
+	}
+}
+
+static const char *
+aeabi_fp_exceptions(uint64_t fe)
+{
+	static char s_fp_e[32];
+
+	switch (fe) {
+	case 0: return "Unused";
+	case 1: return "Needed";
+	default:
+		snprintf(s_fp_e, sizeof(s_fp_e), "Unknown (%ju)",
+		    (uintmax_t) fe);
+		return (s_fp_e);
+	}
+}
+
+static const char *
+aeabi_fp_user_exceptions(uint64_t fu)
+{
+	static char s_fp_u[32];
+
+	switch (fu) {
+	case 0: return "Unused";
+	case 1: return "Needed";
+	default:
+		snprintf(s_fp_u, sizeof(s_fp_u), "Unknown (%ju)",
+		    (uintmax_t) fu);
+		return (s_fp_u);
+	}
+}
+
+static const char *
+aeabi_fp_number_model(uint64_t fn)
+{
+	static char s_fp_n[32];
+
+	switch (fn) {
+	case 0: return "Unused";
+	case 1: return "IEEE 754 normal";
+	case 2: return "RTABI";
+	case 3: return "IEEE 754";
+	default:
+		snprintf(s_fp_n, sizeof(s_fp_n), "Unknown (%ju)",
+		    (uintmax_t) fn);
+		return (s_fp_n);
+	}
+}
+
+static const char *
+aeabi_fp_16bit_format(uint64_t fp16)
+{
+	static char s_fp_16[64];
+
+	switch (fp16) {
+	case 0: return "None";
+	case 1: return "IEEE 754";
+	case 2: return "VFPv3/Advanced SIMD (alternative format)";
+	default:
+		snprintf(s_fp_16, sizeof(s_fp_16), "Unknown (%ju)",
+		    (uintmax_t) fp16);
+		return (s_fp_16);
+	}
+}
+
+static const char *
+aeabi_mpext(uint64_t mp)
+{
+	static char s_mp[32];
+
+	switch (mp) {
+	case 0: return "Not allowed";
+	case 1: return "Allowed";
+	default:
+		snprintf(s_mp, sizeof(s_mp), "Unknown (%ju)",
+		    (uintmax_t) mp);
+		return (s_mp);
+	}
+}
+
+static const char *
+aeabi_div(uint64_t du)
+{
+	static char s_du[32];
+
+	switch (du) {
+	case 0: return "Yes (V7-R/V7-M)";
+	case 1: return "No";
+	case 2: return "Yes (V7-A)";
+	default:
+		snprintf(s_du, sizeof(s_du), "Unknown (%ju)",
+		    (uintmax_t) du);
+		return (s_du);
+	}
+}
+
+static const char *
+aeabi_t2ee(uint64_t t2ee)
+{
+	static char s_t2ee[32];
+
+	switch (t2ee) {
+	case 0: return "Not allowed";
+	case 1: return "Allowed";
+	default:
+		snprintf(s_t2ee, sizeof(s_t2ee), "Unknown(%ju)",
+		    (uintmax_t) t2ee);
+		return (s_t2ee);
+	}
+
+}
+
+static const char *
+aeabi_hardfp(uint64_t hfp)
+{
+	static char s_hfp[32];
+
+	switch (hfp) {
+	case 0: return "Tag_FP_arch";
+	case 1: return "only SP";
+	case 2: return "only DP";
+	case 3: return "both SP and DP";
+	default:
+		snprintf(s_hfp, sizeof(s_hfp), "Unknown (%ju)",
+		    (uintmax_t) hfp);
+		return (s_hfp);
+	}
+}
+
+static const char *
+aeabi_vfp_args(uint64_t va)
+{
+	static char s_va[32];
+
+	switch (va) {
+	case 0: return "AAPCS (base variant)";
+	case 1: return "AAPCS (VFP variant)";
+	case 2: return "toolchain-specific";
+	default:
+		snprintf(s_va, sizeof(s_va), "Unknown (%ju)", (uintmax_t) va);
+		return (s_va);
+	}
+}
+
+static const char *
+aeabi_wmmx_args(uint64_t wa)
+{
+	static char s_wa[32];
+
+	switch (wa) {
+	case 0: return "AAPCS (base variant)";
+	case 1: return "Intel WMMX";
+	case 2: return "toolchain-specific";
+	default:
+		snprintf(s_wa, sizeof(s_wa), "Unknown(%ju)", (uintmax_t) wa);
+		return (s_wa);
+	}
+}
+
+static const char *
+aeabi_unaligned_access(uint64_t ua)
+{
+	static char s_ua[32];
+
+	switch (ua) {
+	case 0: return "Not allowed";
+	case 1: return "Allowed";
+	default:
+		snprintf(s_ua, sizeof(s_ua), "Unknown(%ju)", (uintmax_t) ua);
+		return (s_ua);
+	}
+}
+
+static const char *
+aeabi_fp_hpext(uint64_t fh)
+{
+	static char s_fh[32];
+
+	switch (fh) {
+	case 0: return "Not allowed";
+	case 1: return "Allowed";
+	default:
+		snprintf(s_fh, sizeof(s_fh), "Unknown(%ju)", (uintmax_t) fh);
+		return (s_fh);
+	}
+}
+
+static const char *
+aeabi_optm_goal(uint64_t og)
+{
+	static char s_og[32];
+
+	switch (og) {
+	case 0: return "None";
+	case 1: return "Speed";
+	case 2: return "Speed aggressive";
+	case 3: return "Space";
+	case 4: return "Space aggressive";
+	case 5: return "Debugging";
+	case 6: return "Best Debugging";
+	default:
+		snprintf(s_og, sizeof(s_og), "Unknown(%ju)", (uintmax_t) og);
+		return (s_og);
+	}
+}
+
+static const char *
+aeabi_fp_optm_goal(uint64_t fog)
+{
+	static char s_fog[32];
+
+	switch (fog) {
+	case 0: return "None";
+	case 1: return "Speed";
+	case 2: return "Speed aggressive";
+	case 3: return "Space";
+	case 4: return "Space aggressive";
+	case 5: return "Accurary";
+	case 6: return "Best Accurary";
+	default:
+		snprintf(s_fog, sizeof(s_fog), "Unknown(%ju)",
+		    (uintmax_t) fog);
+		return (s_fog);
+	}
+}
+
+static const char *
+aeabi_virtual(uint64_t vt)
+{
+	static char s_virtual[64];
+
+	switch (vt) {
+	case 0: return "No";
+	case 1: return "TrustZone";
+	case 2: return "Virtualization extension";
+	case 3: return "TrustZone and virtualization extension";
+	default:
+		snprintf(s_virtual, sizeof(s_virtual), "Unknown(%ju)",
+		    (uintmax_t) vt);
+		return (s_virtual);
+	}
+}
+
+static struct {
+	uint64_t tag;
+	const char *s_tag;
+	const char *(*get_desc)(uint64_t val);
+} aeabi_tags[] = {
+	{4, "Tag_CPU_raw_name", NULL},
+	{5, "Tag_CPU_name", NULL},
+	{6, "Tag_CPU_arch", aeabi_cpu_arch},
+	{7, "Tag_CPU_arch_profile", aeabi_cpu_arch_profile},
+	{8, "Tag_ARM_ISA_use", aeabi_arm_isa},
+	{9, "Tag_THUMB_ISA_use", aeabi_thumb_isa},
+	{10, "Tag_FP_arch", aeabi_fp_arch},
+	{11, "Tag_WMMX_arch", aeabi_wmmx_arch},
+	{12, "Tag_Advanced_SIMD_arch", aeabi_adv_simd_arch},
+	{13, "Tag_PCS_config", aeabi_pcs_config},
+	{14, "Tag_ABI_PCS_R9_use", aeabi_pcs_r9},
+	{15, "Tag_ABI_PCS_RW_data", aeabi_pcs_rw},
+	{16, "Tag_ABI_PCS_RO_data", aeabi_pcs_ro},
+	{17, "Tag_ABI_PCS_GOT_use", aeabi_pcs_got},
+	{18, "Tag_ABI_PCS_wchar_t", aeabi_pcs_wchar_t},
+	{19, "Tag_ABI_FP_rounding", aeabi_fp_rounding},
+	{20, "Tag_ABI_FP_denormal", aeabi_fp_denormal},
+	{21, "Tag_ABI_FP_exceptions", aeabi_fp_exceptions},
+	{22, "Tag_ABI_FP_user_exceptions", aeabi_fp_user_exceptions},
+	{23, "Tag_ABI_FP_number_model", aeabi_fp_number_model},
+	{24, "Tag_ABI_align_needed", aeabi_align_needed},
+	{25, "Tag_ABI_align_preserved", aeabi_align_preserved},
+	{26, "Tag_ABI_enum_size", aeabi_enum_size},
+	{27, "Tag_ABI_HardFP_use", aeabi_hardfp},
+	{28, "Tag_ABI_VFP_args", aeabi_vfp_args},
+	{29, "Tag_ABI_WMMX_args", aeabi_wmmx_args},
+	{30, "Tag_ABI_optimization_goals", aeabi_optm_goal},
+	{31, "Tag_ABI_FP_optimization_goals", aeabi_fp_optm_goal},
+	{32, "Tag_compatibility", NULL},
+	{34, "Tag_CPU_unaligned_access", aeabi_unaligned_access},
+	{36, "Tag_FP_HP_extension", aeabi_fp_hpext},
+	{38, "Tag_ABI_FP_16bit_format", aeabi_fp_16bit_format},
+	{42, "Tag_MPextension_use", aeabi_mpext},
+	{44, "Tag_DIV_use", aeabi_div},
+	{64, "Tag_nodefaults", NULL},
+	{65, "Tag_also_compatible_with", NULL},
+	{66, "Tag_T2EE_use", aeabi_t2ee},
+	{67, "Tag_conformance", NULL},
+	{68, "Tag_Virtualization_use", aeabi_virtual},
+	{70, "Tag_MPextension_use", aeabi_mpext},
+};
+
+static const char *
+mips_abi_fp(uint64_t fp)
+{
+	static char s_mips_abi_fp[64];
+
+	switch (fp) {
+	case 0: return "N/A";
+	case 1: return "Hard float (double precision)";
+	case 2: return "Hard float (single precision)";
+	case 3: return "Soft float";
+	case 4: return "64-bit float (-mips32r2 -mfp64)";
+	default:
+		snprintf(s_mips_abi_fp, sizeof(s_mips_abi_fp), "Unknown(%ju)",
+		    (uintmax_t) fp);
+		return (s_mips_abi_fp);
+	}
+}
+
+static const char *
+ppc_abi_fp(uint64_t fp)
+{
+	static char s_ppc_abi_fp[64];
+
+	switch (fp) {
+	case 0: return "N/A";
+	case 1: return "Hard float (double precision)";
+	case 2: return "Soft float";
+	case 3: return "Hard float (single precision)";
+	default:
+		snprintf(s_ppc_abi_fp, sizeof(s_ppc_abi_fp), "Unknown(%ju)",
+		    (uintmax_t) fp);
+		return (s_ppc_abi_fp);
+	}
+}
+
+static const char *
+ppc_abi_vector(uint64_t vec)
+{
+	static char s_vec[64];
+
+	switch (vec) {
+	case 0: return "N/A";
+	case 1: return "Generic purpose registers";
+	case 2: return "AltiVec registers";
+	case 3: return "SPE registers";
+	default:
+		snprintf(s_vec, sizeof(s_vec), "Unknown(%ju)", (uintmax_t) vec);
+		return (s_vec);
+	}
+}
+
+static const char *
+dwarf_reg(unsigned int mach, unsigned int reg)
+{
+
+	switch (mach) {
+	case EM_386:
+	case EM_IAMCU:
+		switch (reg) {
+		case 0: return "eax";
+		case 1: return "ecx";
+		case 2: return "edx";
+		case 3: return "ebx";
+		case 4: return "esp";
+		case 5: return "ebp";
+		case 6: return "esi";
+		case 7: return "edi";
+		case 8: return "eip";
+		case 9: return "eflags";
+		case 11: return "st0";
+		case 12: return "st1";
+		case 13: return "st2";
+		case 14: return "st3";
+		case 15: return "st4";
+		case 16: return "st5";
+		case 17: return "st6";
+		case 18: return "st7";
+		case 21: return "xmm0";
+		case 22: return "xmm1";
+		case 23: return "xmm2";
+		case 24: return "xmm3";
+		case 25: return "xmm4";
+		case 26: return "xmm5";
+		case 27: return "xmm6";
+		case 28: return "xmm7";
+		case 29: return "mm0";
+		case 30: return "mm1";
+		case 31: return "mm2";
+		case 32: return "mm3";
+		case 33: return "mm4";
+		case 34: return "mm5";
+		case 35: return "mm6";
+		case 36: return "mm7";
+		case 37: return "fcw";
+		case 38: return "fsw";
+		case 39: return "mxcsr";
+		case 40: return "es";
+		case 41: return "cs";
+		case 42: return "ss";
+		case 43: return "ds";
+		case 44: return "fs";
+		case 45: return "gs";
+		case 48: return "tr";
+		case 49: return "ldtr";
+		default: return (NULL);
+		}
+	case EM_X86_64:
+		switch (reg) {
+		case 0: return "rax";
+		case 1: return "rdx";
+		case 2: return "rcx";
+		case 3: return "rbx";
+		case 4: return "rsi";
+		case 5: return "rdi";
+		case 6: return "rbp";
+		case 7: return "rsp";
+		case 16: return "rip";
+		case 17: return "xmm0";
+		case 18: return "xmm1";
+		case 19: return "xmm2";
+		case 20: return "xmm3";
+		case 21: return "xmm4";
+		case 22: return "xmm5";
+		case 23: return "xmm6";
+		case 24: return "xmm7";
+		case 25: return "xmm8";
+		case 26: return "xmm9";
+		case 27: return "xmm10";
+		case 28: return "xmm11";
+		case 29: return "xmm12";
+		case 30: return "xmm13";
+		case 31: return "xmm14";
+		case 32: return "xmm15";
+		case 33: return "st0";
+		case 34: return "st1";
+		case 35: return "st2";
+		case 36: return "st3";
+		case 37: return "st4";
+		case 38: return "st5";
+		case 39: return "st6";
+		case 40: return "st7";
+		case 41: return "mm0";
+		case 42: return "mm1";
+		case 43: return "mm2";
+		case 44: return "mm3";
+		case 45: return "mm4";
+		case 46: return "mm5";
+		case 47: return "mm6";
+		case 48: return "mm7";
+		case 49: return "rflags";
+		case 50: return "es";
+		case 51: return "cs";
+		case 52: return "ss";
+		case 53: return "ds";
+		case 54: return "fs";
+		case 55: return "gs";
+		case 58: return "fs.base";
+		case 59: return "gs.base";
+		case 62: return "tr";
+		case 63: return "ldtr";
+		case 64: return "mxcsr";
+		case 65: return "fcw";
+		case 66: return "fsw";
+		default: return (NULL);
+		}
+	default:
+		return (NULL);
+	}
+}
+
+static void
+dump_ehdr(struct readelf *re)
+{
+	size_t		 phnum, shnum, shstrndx;
+	int		 i;
+
+	printf("ELF Header:\n");
+
+	/* e_ident[]. */
+	printf("  Magic:   ");
+	for (i = 0; i < EI_NIDENT; i++)
+		printf("%.2x ", re->ehdr.e_ident[i]);
+	putchar('\n');
+
+	/* EI_CLASS. */
+	printf("%-37s%s\n", "  Class:", elf_class(re->ehdr.e_ident[EI_CLASS]));
+
+	/* EI_DATA. */
+	printf("%-37s%s\n", "  Data:", elf_endian(re->ehdr.e_ident[EI_DATA]));
+
+	/* EI_VERSION. */
+	printf("%-37s%d %s\n", "  Version:", re->ehdr.e_ident[EI_VERSION],
+	    elf_ver(re->ehdr.e_ident[EI_VERSION]));
+
+	/* EI_OSABI. */
+	printf("%-37s%s\n", "  OS/ABI:", elf_osabi(re->ehdr.e_ident[EI_OSABI]));
+
+	/* EI_ABIVERSION. */
+	printf("%-37s%d\n", "  ABI Version:", re->ehdr.e_ident[EI_ABIVERSION]);
+
+	/* e_type. */
+	printf("%-37s%s\n", "  Type:", elf_type(re->ehdr.e_type));
+
+	/* e_machine. */
+	printf("%-37s%s\n", "  Machine:", elf_machine(re->ehdr.e_machine));
+
+	/* e_version. */
+	printf("%-37s%#x\n", "  Version:", re->ehdr.e_version);
+
+	/* e_entry. */
+	printf("%-37s%#jx\n", "  Entry point address:",
+	    (uintmax_t)re->ehdr.e_entry);
+
+	/* e_phoff. */
+	printf("%-37s%ju (bytes into file)\n", "  Start of program headers:",
+	    (uintmax_t)re->ehdr.e_phoff);
+
+	/* e_shoff. */
+	printf("%-37s%ju (bytes into file)\n", "  Start of section headers:",
+	    (uintmax_t)re->ehdr.e_shoff);
+
+	/* e_flags. */
+	printf("%-37s%#x", "  Flags:", re->ehdr.e_flags);
+	dump_eflags(re, re->ehdr.e_flags);
+	putchar('\n');
+
+	/* e_ehsize. */
+	printf("%-37s%u (bytes)\n", "  Size of this header:",
+	    re->ehdr.e_ehsize);
+
+	/* e_phentsize. */
+	printf("%-37s%u (bytes)\n", "  Size of program headers:",
+	    re->ehdr.e_phentsize);
+
+	/* e_phnum. */
+	printf("%-37s%u", "  Number of program headers:", re->ehdr.e_phnum);
+	if (re->ehdr.e_phnum == PN_XNUM) {
+		/* Extended program header numbering is in use. */
+		if (elf_getphnum(re->elf, &phnum))
+			printf(" (%zu)", phnum);
+	}
+	putchar('\n');
+
+	/* e_shentsize. */
+	printf("%-37s%u (bytes)\n", "  Size of section headers:",
+	    re->ehdr.e_shentsize);
+
+	/* e_shnum. */
+	printf("%-37s%u", "  Number of section headers:", re->ehdr.e_shnum);
+	if (re->ehdr.e_shnum == SHN_UNDEF) {
+		/* Extended section numbering is in use. */
+		if (elf_getshnum(re->elf, &shnum))
+			printf(" (%ju)", (uintmax_t)shnum);
+	}
+	putchar('\n');
+
+	/* e_shstrndx. */
+	printf("%-37s%u", "  Section header string table index:",
+	    re->ehdr.e_shstrndx);
+	if (re->ehdr.e_shstrndx == SHN_XINDEX) {
+		/* Extended section numbering is in use. */
+		if (elf_getshstrndx(re->elf, &shstrndx))
+			printf(" (%ju)", (uintmax_t)shstrndx);
+	}
+	putchar('\n');
+}
+
+static void
+dump_eflags(struct readelf *re, uint64_t e_flags)
+{
+	struct eflags_desc *edesc;
+	int arm_eabi;
+
+	edesc = NULL;
+	switch (re->ehdr.e_machine) {
+	case EM_ARM:
+		arm_eabi = (e_flags & EF_ARM_EABIMASK) >> 24;
+		if (arm_eabi == 0)
+			printf(", GNU EABI");
+		else if (arm_eabi <= 5)
+			printf(", Version%d EABI", arm_eabi);
+		edesc = arm_eflags_desc;
+		break;
+	case EM_MIPS:
+	case EM_MIPS_RS3_LE:
+		switch ((e_flags & EF_MIPS_ARCH) >> 28) {
+		case 0:	printf(", mips1"); break;
+		case 1: printf(", mips2"); break;
+		case 2: printf(", mips3"); break;
+		case 3: printf(", mips4"); break;
+		case 4: printf(", mips5"); break;
+		case 5: printf(", mips32"); break;
+		case 6: printf(", mips64"); break;
+		case 7: printf(", mips32r2"); break;
+		case 8: printf(", mips64r2"); break;
+		default: break;
+		}
+		switch ((e_flags & 0x00FF0000) >> 16) {
+		case 0x81: printf(", 3900"); break;
+		case 0x82: printf(", 4010"); break;
+		case 0x83: printf(", 4100"); break;
+		case 0x85: printf(", 4650"); break;
+		case 0x87: printf(", 4120"); break;
+		case 0x88: printf(", 4111"); break;
+		case 0x8a: printf(", sb1"); break;
+		case 0x8b: printf(", octeon"); break;
+		case 0x8c: printf(", xlr"); break;
+		case 0x91: printf(", 5400"); break;
+		case 0x98: printf(", 5500"); break;
+		case 0x99: printf(", 9000"); break;
+		case 0xa0: printf(", loongson-2e"); break;
+		case 0xa1: printf(", loongson-2f"); break;
+		default: break;
+		}
+		switch ((e_flags & 0x0000F000) >> 12) {
+		case 1: printf(", o32"); break;
+		case 2: printf(", o64"); break;
+		case 3: printf(", eabi32"); break;
+		case 4: printf(", eabi64"); break;
+		default: break;
+		}
+		edesc = mips_eflags_desc;
+		break;
+	case EM_PPC:
+	case EM_PPC64:
+		edesc = powerpc_eflags_desc;
+		break;
+	case EM_SPARC:
+	case EM_SPARC32PLUS:
+	case EM_SPARCV9:
+		switch ((e_flags & EF_SPARCV9_MM)) {
+		case EF_SPARCV9_TSO: printf(", tso"); break;
+		case EF_SPARCV9_PSO: printf(", pso"); break;
+		case EF_SPARCV9_MM: printf(", rmo"); break;
+		default: break;
+		}
+		edesc = sparc_eflags_desc;
+		break;
+	default:
+		break;
+	}
+
+	if (edesc != NULL) {
+		while (edesc->desc != NULL) {
+			if (e_flags & edesc->flag)
+				printf(", %s", edesc->desc);
+			edesc++;
+		}
+	}
+}
+
+static void
+dump_phdr(struct readelf *re)
+{
+	const char	*rawfile;
+	GElf_Phdr	 phdr;
+	size_t		 phnum, size;
+	int		 i, j;
+
+#define	PH_HDR	"Type", "Offset", "VirtAddr", "PhysAddr", "FileSiz",	\
+		"MemSiz", "Flg", "Align"
+#define	PH_CT	phdr_type(re->ehdr.e_machine, phdr.p_type),		\
+		(uintmax_t)phdr.p_offset, (uintmax_t)phdr.p_vaddr,	\
+		(uintmax_t)phdr.p_paddr, (uintmax_t)phdr.p_filesz,	\
+		(uintmax_t)phdr.p_memsz,				\
+		phdr.p_flags & PF_R ? 'R' : ' ',			\
+		phdr.p_flags & PF_W ? 'W' : ' ',			\
+		phdr.p_flags & PF_X ? 'E' : ' ',			\
+		(uintmax_t)phdr.p_align
+
+	if (elf_getphnum(re->elf, &phnum) == 0) {
+		warnx("elf_getphnum failed: %s", elf_errmsg(-1));
+		return;
+	}
+	if (phnum == 0) {
+		printf("\nThere are no program headers in this file.\n");
+		return;
+	}
+
+	printf("\nElf file type is %s", elf_type(re->ehdr.e_type));
+	printf("\nEntry point 0x%jx\n", (uintmax_t)re->ehdr.e_entry);
+	printf("There are %ju program headers, starting at offset %ju\n",
+	    (uintmax_t)phnum, (uintmax_t)re->ehdr.e_phoff);
+
+	/* Dump program headers. */
+	printf("\nProgram Headers:\n");
+	if (re->ec == ELFCLASS32)
+		printf("  %-15s%-9s%-11s%-11s%-8s%-8s%-4s%s\n", PH_HDR);
+	else if (re->options & RE_WW)
+		printf("  %-15s%-9s%-19s%-19s%-9s%-9s%-4s%s\n", PH_HDR);
+	else
+		printf("  %-15s%-19s%-19s%s\n                 %-19s%-20s"
+		    "%-7s%s\n", PH_HDR);
+	for (i = 0; (size_t) i < phnum; i++) {
+		if (gelf_getphdr(re->elf, i, &phdr) != &phdr) {
+			warnx("gelf_getphdr failed: %s", elf_errmsg(-1));
+			continue;
+		}
+		/* TODO: Add arch-specific segment type dump. */
+		if (re->ec == ELFCLASS32)
+			printf("  %-14.14s 0x%6.6jx 0x%8.8jx 0x%8.8jx "
+			    "0x%5.5jx 0x%5.5jx %c%c%c %#jx\n", PH_CT);
+		else if (re->options & RE_WW)
+			printf("  %-14.14s 0x%6.6jx 0x%16.16jx 0x%16.16jx "
+			    "0x%6.6jx 0x%6.6jx %c%c%c %#jx\n", PH_CT);
+		else
+			printf("  %-14.14s 0x%16.16jx 0x%16.16jx 0x%16.16jx\n"
+			    "                 0x%16.16jx 0x%16.16jx  %c%c%c"
+			    "    %#jx\n", PH_CT);
+		if (phdr.p_type == PT_INTERP) {
+			if ((rawfile = elf_rawfile(re->elf, &size)) == NULL) {
+				warnx("elf_rawfile failed: %s", elf_errmsg(-1));
+				continue;
+			}
+			if (phdr.p_offset >= size) {
+				warnx("invalid program header offset");
+				continue;
+			}
+			printf("      [Requesting program interpreter: %s]\n",
+				rawfile + phdr.p_offset);
+		}
+	}
+
+	/* Dump section to segment mapping. */
+	if (re->shnum == 0)
+		return;
+	printf("\n Section to Segment mapping:\n");
+	printf("  Segment Sections...\n");
+	for (i = 0; (size_t)i < phnum; i++) {
+		if (gelf_getphdr(re->elf, i, &phdr) != &phdr) {
+			warnx("gelf_getphdr failed: %s", elf_errmsg(-1));
+			continue;
+		}
+		printf("   %2.2d     ", i);
+		/* skip NULL section. */
+		for (j = 1; (size_t)j < re->shnum; j++) {
+			if (re->sl[j].off < phdr.p_offset)
+				continue;
+			if (re->sl[j].off + re->sl[j].sz >
+			    phdr.p_offset + phdr.p_filesz &&
+			    re->sl[j].type != SHT_NOBITS)
+				continue;
+			if (re->sl[j].addr < phdr.p_vaddr ||
+			    re->sl[j].addr + re->sl[j].sz >
+			    phdr.p_vaddr + phdr.p_memsz)
+				continue;
+			if (phdr.p_type == PT_TLS &&
+			    (re->sl[j].flags & SHF_TLS) == 0)
+				continue;
+			printf("%s ", re->sl[j].name);
+		}
+		printf("\n");
+	}
+#undef	PH_HDR
+#undef	PH_CT
+}
+
+static char *
+section_flags(struct readelf *re, struct section *s)
+{
+#define BUF_SZ 256
+	static char	buf[BUF_SZ];
+	int		i, p, nb;
+
+	p = 0;
+	nb = re->ec == ELFCLASS32 ? 8 : 16;
+	if (re->options & RE_T) {
+		snprintf(buf, BUF_SZ, "[%*.*jx]: ", nb, nb,
+		    (uintmax_t)s->flags);
+		p += nb + 4;
+	}
+	for (i = 0; section_flag[i].ln != NULL; i++) {
+		if ((s->flags & section_flag[i].value) == 0)
+			continue;
+		if (re->options & RE_T) {
+			snprintf(&buf[p], BUF_SZ - p, "%s, ",
+			    section_flag[i].ln);
+			p += strlen(section_flag[i].ln) + 2;
+		} else
+			buf[p++] = section_flag[i].sn;
+	}
+	if (re->options & RE_T && p > nb + 4)
+		p -= 2;
+	buf[p] = '\0';
+
+	return (buf);
+}
+
+static void
+dump_shdr(struct readelf *re)
+{
+	struct section	*s;
+	int		 i;
+
+#define	S_HDR	"[Nr] Name", "Type", "Addr", "Off", "Size", "ES",	\
+		"Flg", "Lk", "Inf", "Al"
+#define	S_HDRL	"[Nr] Name", "Type", "Address", "Offset", "Size",	\
+		"EntSize", "Flags", "Link", "Info", "Align"
+#define	ST_HDR	"[Nr] Name", "Type", "Addr", "Off", "Size", "ES",	\
+		"Lk", "Inf", "Al", "Flags"
+#define	ST_HDRL	"[Nr] Name", "Type", "Address", "Offset", "Link",	\
+		"Size", "EntSize", "Info", "Align", "Flags"
+#define	S_CT	i, s->name, section_type(re->ehdr.e_machine, s->type),	\
+		(uintmax_t)s->addr, (uintmax_t)s->off, (uintmax_t)s->sz,\
+		(uintmax_t)s->entsize, section_flags(re, s),		\
+		s->link, s->info, (uintmax_t)s->align
+#define	ST_CT	i, s->name, section_type(re->ehdr.e_machine, s->type),  \
+		(uintmax_t)s->addr, (uintmax_t)s->off, (uintmax_t)s->sz,\
+		(uintmax_t)s->entsize, s->link, s->info,		\
+		(uintmax_t)s->align, section_flags(re, s)
+#define	ST_CTL	i, s->name, section_type(re->ehdr.e_machine, s->type),  \
+		(uintmax_t)s->addr, (uintmax_t)s->off, s->link,		\
+		(uintmax_t)s->sz, (uintmax_t)s->entsize, s->info,	\
+		(uintmax_t)s->align, section_flags(re, s)
+
+	if (re->shnum == 0) {
+		printf("\nThere are no sections in this file.\n");
+		return;
+	}
+	printf("There are %ju section headers, starting at offset 0x%jx:\n",
+	    (uintmax_t)re->shnum, (uintmax_t)re->ehdr.e_shoff);
+	printf("\nSection Headers:\n");
+	if (re->ec == ELFCLASS32) {
+		if (re->options & RE_T)
+			printf("  %s\n       %-16s%-9s%-7s%-7s%-5s%-3s%-4s%s\n"
+			    "%12s\n", ST_HDR);
+		else
+			printf("  %-23s%-16s%-9s%-7s%-7s%-3s%-4s%-3s%-4s%s\n",
+			    S_HDR);
+	} else if (re->options & RE_WW) {
+		if (re->options & RE_T)
+			printf("  %s\n       %-16s%-17s%-7s%-7s%-5s%-3s%-4s%s\n"
+			    "%12s\n", ST_HDR);
+		else
+			printf("  %-23s%-16s%-17s%-7s%-7s%-3s%-4s%-3s%-4s%s\n",
+			    S_HDR);
+	} else {
+		if (re->options & RE_T)
+			printf("  %s\n       %-18s%-17s%-18s%s\n       %-18s"
+			    "%-17s%-18s%s\n%12s\n", ST_HDRL);
+		else
+			printf("  %-23s%-17s%-18s%s\n       %-18s%-17s%-7s%"
+			    "-6s%-6s%s\n", S_HDRL);
+	}
+	for (i = 0; (size_t)i < re->shnum; i++) {
+		s = &re->sl[i];
+		if (re->ec == ELFCLASS32) {
+			if (re->options & RE_T)
+				printf("  [%2d] %s\n       %-15.15s %8.8jx"
+				    " %6.6jx %6.6jx %2.2jx  %2u %3u %2ju\n"
+				    "       %s\n", ST_CT);
+			else
+				printf("  [%2d] %-17.17s %-15.15s %8.8jx"
+				    " %6.6jx %6.6jx %2.2jx %3s %2u %3u %2ju\n",
+				    S_CT);
+		} else if (re->options & RE_WW) {
+			if (re->options & RE_T)
+				printf("  [%2d] %s\n       %-15.15s %16.16jx"
+				    " %6.6jx %6.6jx %2.2jx  %2u %3u %2ju\n"
+				    "       %s\n", ST_CT);
+			else
+				printf("  [%2d] %-17.17s %-15.15s %16.16jx"
+				    " %6.6jx %6.6jx %2.2jx %3s %2u %3u %2ju\n",
+				    S_CT);
+		} else {
+			if (re->options & RE_T)
+				printf("  [%2d] %s\n       %-15.15s  %16.16jx"
+				    "  %16.16jx  %u\n       %16.16jx %16.16jx"
+				    "  %-16u  %ju\n       %s\n", ST_CTL);
+			else
+				printf("  [%2d] %-17.17s %-15.15s  %16.16jx"
+				    "  %8.8jx\n       %16.16jx  %16.16jx "
+				    "%3s      %2u   %3u     %ju\n", S_CT);
+		}
+	}
+	if ((re->options & RE_T) == 0)
+		printf("Key to Flags:\n  W (write), A (alloc),"
+		    " X (execute), M (merge), S (strings)\n"
+		    "  I (info), L (link order), G (group), x (unknown)\n"
+		    "  O (extra OS processing required)"
+		    " o (OS specific), p (processor specific)\n");
+
+#undef	S_HDR
+#undef	S_HDRL
+#undef	ST_HDR
+#undef	ST_HDRL
+#undef	S_CT
+#undef	ST_CT
+#undef	ST_CTL
+}
+
+/*
+ * Return number of entries in the given section. We'd prefer ent_count be a
+ * size_t *, but libelf APIs already use int for section indices.
+ */
+static int
+get_ent_count(struct section *s, int *ent_count)
+{
+	if (s->entsize == 0) {
+		warnx("section %s has entry size 0", s->name);
+		return (0);
+	} else if (s->sz / s->entsize > INT_MAX) {
+		warnx("section %s has invalid section count", s->name);
+		return (0);
+	}
+	*ent_count = (int)(s->sz / s->entsize);
+	return (1);
+}
+
+static void
+dump_dynamic(struct readelf *re)
+{
+	GElf_Dyn	 dyn;
+	Elf_Data	*d;
+	struct section	*s;
+	int		 elferr, i, is_dynamic, j, jmax, nentries;
+
+	is_dynamic = 0;
+
+	for (i = 0; (size_t)i < re->shnum; i++) {
+		s = &re->sl[i];
+		if (s->type != SHT_DYNAMIC)
+			continue;
+		(void) elf_errno();
+		if ((d = elf_getdata(s->scn, NULL)) == NULL) {
+			elferr = elf_errno();
+			if (elferr != 0)
+				warnx("elf_getdata failed: %s", elf_errmsg(-1));
+			continue;
+		}
+		if (d->d_size <= 0)
+			continue;
+
+		is_dynamic = 1;
+
+		/* Determine the actual number of table entries. */
+		nentries = 0;
+		if (!get_ent_count(s, &jmax))
+			continue;
+		for (j = 0; j < jmax; j++) {
+			if (gelf_getdyn(d, j, &dyn) != &dyn) {
+				warnx("gelf_getdyn failed: %s",
+				    elf_errmsg(-1));
+				continue;
+			}
+			nentries ++;
+			if (dyn.d_tag == DT_NULL)
+				break;
+                }
+
+		printf("\nDynamic section at offset 0x%jx", (uintmax_t)s->off);
+		printf(" contains %u entries:\n", nentries);
+
+		if (re->ec == ELFCLASS32)
+			printf("%5s%12s%28s\n", "Tag", "Type", "Name/Value");
+		else
+			printf("%5s%20s%28s\n", "Tag", "Type", "Name/Value");
+
+		for (j = 0; j < nentries; j++) {
+			if (gelf_getdyn(d, j, &dyn) != &dyn)
+				continue;
+			/* Dump dynamic entry type. */
+			if (re->ec == ELFCLASS32)
+				printf(" 0x%8.8jx", (uintmax_t)dyn.d_tag);
+			else
+				printf(" 0x%16.16jx", (uintmax_t)dyn.d_tag);
+			printf(" %-20s", dt_type(re->ehdr.e_machine,
+			    dyn.d_tag));
+			/* Dump dynamic entry value. */
+			dump_dyn_val(re, &dyn, s->link);
+		}
+	}
+
+	if (!is_dynamic)
+		printf("\nThere is no dynamic section in this file.\n");
+}
+
+static char *
+timestamp(time_t ti)
+{
+	static char ts[32];
+	struct tm *t;
+
+	t = gmtime(&ti);
+	snprintf(ts, sizeof(ts), "%04d-%02d-%02dT%02d:%02d:%02d",
+	    t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour,
+	    t->tm_min, t->tm_sec);
+
+	return (ts);
+}
+
+static const char *
+dyn_str(struct readelf *re, uint32_t stab, uint64_t d_val)
+{
+	const char *name;
+
+	if (stab == SHN_UNDEF)
+		name = "ERROR";
+	else if ((name = elf_strptr(re->elf, stab, d_val)) == NULL) {
+		(void) elf_errno(); /* clear error */
+		name = "ERROR";
+	}
+
+	return (name);
+}
+
+static void
+dump_arch_dyn_val(struct readelf *re, GElf_Dyn *dyn)
+{
+	switch (re->ehdr.e_machine) {
+	case EM_MIPS:
+	case EM_MIPS_RS3_LE:
+		switch (dyn->d_tag) {
+		case DT_MIPS_RLD_VERSION:
+		case DT_MIPS_LOCAL_GOTNO:
+		case DT_MIPS_CONFLICTNO:
+		case DT_MIPS_LIBLISTNO:
+		case DT_MIPS_SYMTABNO:
+		case DT_MIPS_UNREFEXTNO:
+		case DT_MIPS_GOTSYM:
+		case DT_MIPS_HIPAGENO:
+		case DT_MIPS_DELTA_CLASS_NO:
+		case DT_MIPS_DELTA_INSTANCE_NO:
+		case DT_MIPS_DELTA_RELOC_NO:
+		case DT_MIPS_DELTA_SYM_NO:
+		case DT_MIPS_DELTA_CLASSSYM_NO:
+		case DT_MIPS_LOCALPAGE_GOTIDX:
+		case DT_MIPS_LOCAL_GOTIDX:
+		case DT_MIPS_HIDDEN_GOTIDX:
+		case DT_MIPS_PROTECTED_GOTIDX:
+			printf(" %ju\n", (uintmax_t) dyn->d_un.d_val);
+			break;
+		case DT_MIPS_ICHECKSUM:
+		case DT_MIPS_FLAGS:
+		case DT_MIPS_BASE_ADDRESS:
+		case DT_MIPS_CONFLICT:
+		case DT_MIPS_LIBLIST:
+		case DT_MIPS_RLD_MAP:
+		case DT_MIPS_DELTA_CLASS:
+		case DT_MIPS_DELTA_INSTANCE:
+		case DT_MIPS_DELTA_RELOC:
+		case DT_MIPS_DELTA_SYM:
+		case DT_MIPS_DELTA_CLASSSYM:
+		case DT_MIPS_CXX_FLAGS:
+		case DT_MIPS_PIXIE_INIT:
+		case DT_MIPS_SYMBOL_LIB:
+		case DT_MIPS_OPTIONS:
+		case DT_MIPS_INTERFACE:
+		case DT_MIPS_DYNSTR_ALIGN:
+		case DT_MIPS_INTERFACE_SIZE:
+		case DT_MIPS_RLD_TEXT_RESOLVE_ADDR:
+		case DT_MIPS_COMPACT_SIZE:
+		case DT_MIPS_GP_VALUE:
+		case DT_MIPS_AUX_DYNAMIC:
+		case DT_MIPS_PLTGOT:
+		case DT_MIPS_RLD_OBJ_UPDATE:
+		case DT_MIPS_RWPLT:
+			printf(" 0x%jx\n", (uintmax_t) dyn->d_un.d_val);
+			break;
+		case DT_MIPS_IVERSION:
+		case DT_MIPS_PERF_SUFFIX:
+		case DT_MIPS_TIME_STAMP:
+			printf(" %s\n", timestamp(dyn->d_un.d_val));
+			break;
+		default:
+			printf("\n");
+			break;
+		}
+		break;
+	default:
+		printf("\n");
+		break;
+	}
+}
+
+static void
+dump_dyn_val(struct readelf *re, GElf_Dyn *dyn, uint32_t stab)
+{
+	const char *name;
+
+	if (dyn->d_tag >= DT_LOPROC && dyn->d_tag <= DT_HIPROC &&
+	    dyn->d_tag != DT_AUXILIARY && dyn->d_tag != DT_FILTER) {
+		dump_arch_dyn_val(re, dyn);
+		return;
+	}
+
+	/* These entry values are index into the string table. */
+	name = NULL;
+	if (dyn->d_tag == DT_AUXILIARY || dyn->d_tag == DT_FILTER ||
+	    dyn->d_tag == DT_NEEDED || dyn->d_tag == DT_SONAME ||
+	    dyn->d_tag == DT_RPATH || dyn->d_tag == DT_RUNPATH)
+		name = dyn_str(re, stab, dyn->d_un.d_val);
+
+	switch(dyn->d_tag) {
+	case DT_NULL:
+	case DT_PLTGOT:
+	case DT_HASH:
+	case DT_STRTAB:
+	case DT_SYMTAB:
+	case DT_RELA:
+	case DT_INIT:
+	case DT_SYMBOLIC:
+	case DT_REL:
+	case DT_DEBUG:
+	case DT_TEXTREL:
+	case DT_JMPREL:
+	case DT_FINI:
+	case DT_VERDEF:
+	case DT_VERNEED:
+	case DT_VERSYM:
+	case DT_GNU_HASH:
+	case DT_GNU_LIBLIST:
+	case DT_GNU_CONFLICT:
+		printf(" 0x%jx\n", (uintmax_t) dyn->d_un.d_val);
+		break;
+	case DT_PLTRELSZ:
+	case DT_RELASZ:
+	case DT_RELAENT:
+	case DT_STRSZ:
+	case DT_SYMENT:
+	case DT_RELSZ:
+	case DT_RELENT:
+	case DT_PREINIT_ARRAYSZ:
+	case DT_INIT_ARRAYSZ:
+	case DT_FINI_ARRAYSZ:
+	case DT_GNU_CONFLICTSZ:
+	case DT_GNU_LIBLISTSZ:
+		printf(" %ju (bytes)\n", (uintmax_t) dyn->d_un.d_val);
+		break;
+ 	case DT_RELACOUNT:
+	case DT_RELCOUNT:
+	case DT_VERDEFNUM:
+	case DT_VERNEEDNUM:
+		printf(" %ju\n", (uintmax_t) dyn->d_un.d_val);
+		break;
+	case DT_AUXILIARY:
+		printf(" Auxiliary library: [%s]\n", name);
+		break;
+	case DT_FILTER:
+		printf(" Filter library: [%s]\n", name);
+		break;
+	case DT_NEEDED:
+		printf(" Shared library: [%s]\n", name);
+		break;
+	case DT_SONAME:
+		printf(" Library soname: [%s]\n", name);
+		break;
+	case DT_RPATH:
+		printf(" Library rpath: [%s]\n", name);
+		break;
+	case DT_RUNPATH:
+		printf(" Library runpath: [%s]\n", name);
+		break;
+	case DT_PLTREL:
+		printf(" %s\n", dt_type(re->ehdr.e_machine, dyn->d_un.d_val));
+		break;
+	case DT_GNU_PRELINKED:
+		printf(" %s\n", timestamp(dyn->d_un.d_val));
+		break;
+	default:
+		printf("\n");
+	}
+}
+
+static void
+dump_rel(struct readelf *re, struct section *s, Elf_Data *d)
+{
+	GElf_Rel r;
+	const char *symname;
+	uint64_t symval;
+	int i, len;
+	uint32_t type;
+	uint8_t type2, type3;
+
+	if (s->link >= re->shnum)
+		return;
+
+#define	REL_HDR "r_offset", "r_info", "r_type", "st_value", "st_name"
+#define	REL_CT32 (uintmax_t)r.r_offset, (uintmax_t)r.r_info,	    \
+		elftc_reloc_type_str(re->ehdr.e_machine,	    \
+		ELF32_R_TYPE(r.r_info)), (uintmax_t)symval, symname
+#define	REL_CT64 (uintmax_t)r.r_offset, (uintmax_t)r.r_info,	    \
+		elftc_reloc_type_str(re->ehdr.e_machine, type),	    \
+		(uintmax_t)symval, symname
+
+	printf("\nRelocation section (%s):\n", s->name);
+	if (re->ec == ELFCLASS32)
+		printf("%-8s %-8s %-19s %-8s %s\n", REL_HDR);
+	else {
+		if (re->options & RE_WW)
+			printf("%-16s %-16s %-24s %-16s %s\n", REL_HDR);
+		else
+			printf("%-12s %-12s %-19s %-16s %s\n", REL_HDR);
+	}
+	assert(d->d_size == s->sz);
+	if (!get_ent_count(s, &len))
+		return;
+	for (i = 0; i < len; i++) {
+		if (gelf_getrel(d, i, &r) != &r) {
+			warnx("gelf_getrel failed: %s", elf_errmsg(-1));
+			continue;
+		}
+		symname = get_symbol_name(re, s->link, GELF_R_SYM(r.r_info));
+		symval = get_symbol_value(re, s->link, GELF_R_SYM(r.r_info));
+		if (re->ec == ELFCLASS32) {
+			r.r_info = ELF32_R_INFO(ELF64_R_SYM(r.r_info),
+			    ELF64_R_TYPE(r.r_info));
+			printf("%8.8jx %8.8jx %-19.19s %8.8jx %s\n", REL_CT32);
+		} else {
+			type = ELF64_R_TYPE(r.r_info);
+			if (re->ehdr.e_machine == EM_MIPS) {
+				type2 = (type >> 8) & 0xFF;
+				type3 = (type >> 16) & 0xFF;
+				type = type & 0xFF;
+			} else {
+				type2 = type3 = 0;
+			}
+			if (re->options & RE_WW)
+				printf("%16.16jx %16.16jx %-24.24s"
+				    " %16.16jx %s\n", REL_CT64);
+			else
+				printf("%12.12jx %12.12jx %-19.19s"
+				    " %16.16jx %s\n", REL_CT64);
+			if (re->ehdr.e_machine == EM_MIPS) {
+				if (re->options & RE_WW) {
+					printf("%32s: %s\n", "Type2",
+					    elftc_reloc_type_str(EM_MIPS,
+					    type2));
+					printf("%32s: %s\n", "Type3",
+					    elftc_reloc_type_str(EM_MIPS,
+					    type3));
+				} else {
+					printf("%24s: %s\n", "Type2",
+					    elftc_reloc_type_str(EM_MIPS,
+					    type2));
+					printf("%24s: %s\n", "Type3",
+					    elftc_reloc_type_str(EM_MIPS,
+					    type3));
+				}
+			}
+		}
+	}
+
+#undef	REL_HDR
+#undef	REL_CT
+}
+
+static void
+dump_rela(struct readelf *re, struct section *s, Elf_Data *d)
+{
+	GElf_Rela r;
+	const char *symname;
+	uint64_t symval;
+	int i, len;
+	uint32_t type;
+	uint8_t type2, type3;
+
+	if (s->link >= re->shnum)
+		return;
+
+#define	RELA_HDR "r_offset", "r_info", "r_type", "st_value", \
+		"st_name + r_addend"
+#define	RELA_CT32 (uintmax_t)r.r_offset, (uintmax_t)r.r_info,	    \
+		elftc_reloc_type_str(re->ehdr.e_machine,	    \
+		ELF32_R_TYPE(r.r_info)), (uintmax_t)symval, symname
+#define	RELA_CT64 (uintmax_t)r.r_offset, (uintmax_t)r.r_info,	    \
+		elftc_reloc_type_str(re->ehdr.e_machine, type),	    \
+		(uintmax_t)symval, symname
+
+	printf("\nRelocation section with addend (%s):\n", s->name);
+	if (re->ec == ELFCLASS32)
+		printf("%-8s %-8s %-19s %-8s %s\n", RELA_HDR);
+	else {
+		if (re->options & RE_WW)
+			printf("%-16s %-16s %-24s %-16s %s\n", RELA_HDR);
+		else
+			printf("%-12s %-12s %-19s %-16s %s\n", RELA_HDR);
+	}
+	assert(d->d_size == s->sz);
+	if (!get_ent_count(s, &len))
+		return;
+	for (i = 0; i < len; i++) {
+		if (gelf_getrela(d, i, &r) != &r) {
+			warnx("gelf_getrel failed: %s", elf_errmsg(-1));
+			continue;
+		}
+		symname = get_symbol_name(re, s->link, GELF_R_SYM(r.r_info));
+		symval = get_symbol_value(re, s->link, GELF_R_SYM(r.r_info));
+		if (re->ec == ELFCLASS32) {
+			r.r_info = ELF32_R_INFO(ELF64_R_SYM(r.r_info),
+			    ELF64_R_TYPE(r.r_info));
+			printf("%8.8jx %8.8jx %-19.19s %8.8jx %s", RELA_CT32);
+			printf(" + %x\n", (uint32_t) r.r_addend);
+		} else {
+			type = ELF64_R_TYPE(r.r_info);
+			if (re->ehdr.e_machine == EM_MIPS) {
+				type2 = (type >> 8) & 0xFF;
+				type3 = (type >> 16) & 0xFF;
+				type = type & 0xFF;
+			} else {
+				type2 = type3 = 0;
+			}
+			if (re->options & RE_WW)
+				printf("%16.16jx %16.16jx %-24.24s"
+				    " %16.16jx %s", RELA_CT64);
+			else
+				printf("%12.12jx %12.12jx %-19.19s"
+				    " %16.16jx %s", RELA_CT64);
+			printf(" + %jx\n", (uintmax_t) r.r_addend);
+			if (re->ehdr.e_machine == EM_MIPS) {
+				if (re->options & RE_WW) {
+					printf("%32s: %s\n", "Type2",
+					    elftc_reloc_type_str(EM_MIPS,
+					    type2));
+					printf("%32s: %s\n", "Type3",
+					    elftc_reloc_type_str(EM_MIPS,
+					    type3));
+				} else {
+					printf("%24s: %s\n", "Type2",
+					    elftc_reloc_type_str(EM_MIPS,
+					    type2));
+					printf("%24s: %s\n", "Type3",
+					    elftc_reloc_type_str(EM_MIPS,
+					    type3));
+				}
+			}
+		}
+	}
+
+#undef	RELA_HDR
+#undef	RELA_CT
+}
+
+static void
+dump_reloc(struct readelf *re)
+{
+	struct section *s;
+	Elf_Data *d;
+	int i, elferr;
+
+	for (i = 0; (size_t)i < re->shnum; i++) {
+		s = &re->sl[i];
+		if (s->type == SHT_REL || s->type == SHT_RELA) {
+			(void) elf_errno();
+			if ((d = elf_getdata(s->scn, NULL)) == NULL) {
+				elferr = elf_errno();
+				if (elferr != 0)
+					warnx("elf_getdata failed: %s",
+					    elf_errmsg(elferr));
+				continue;
+			}
+			if (s->type == SHT_REL)
+				dump_rel(re, s, d);
+			else
+				dump_rela(re, s, d);
+		}
+	}
+}
+
+static void
+dump_symtab(struct readelf *re, int i)
+{
+	struct section *s;
+	Elf_Data *d;
+	GElf_Sym sym;
+	const char *name;
+	uint32_t stab;
+	int elferr, j, len;
+	uint16_t vs;
+
+	s = &re->sl[i];
+	if (s->link >= re->shnum)
+		return;
+	stab = s->link;
+	(void) elf_errno();
+	if ((d = elf_getdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_getdata failed: %s", elf_errmsg(elferr));
+		return;
+	}
+	if (d->d_size <= 0)
+		return;
+	if (!get_ent_count(s, &len))
+		return;
+	printf("Symbol table (%s)", s->name);
+	printf(" contains %d entries:\n", len);
+	printf("%7s%9s%14s%5s%8s%6s%9s%5s\n", "Num:", "Value", "Size", "Type",
+	    "Bind", "Vis", "Ndx", "Name");
+
+	for (j = 0; j < len; j++) {
+		if (gelf_getsym(d, j, &sym) != &sym) {
+			warnx("gelf_getsym failed: %s", elf_errmsg(-1));
+			continue;
+		}
+		printf("%6d:", j);
+		printf(" %16.16jx", (uintmax_t) sym.st_value);
+		printf(" %5ju", (uintmax_t) sym.st_size);
+		printf(" %-7s", st_type(re->ehdr.e_machine,
+		    re->ehdr.e_ident[EI_OSABI], GELF_ST_TYPE(sym.st_info)));
+		printf(" %-6s", st_bind(GELF_ST_BIND(sym.st_info)));
+		printf(" %-8s", st_vis(GELF_ST_VISIBILITY(sym.st_other)));
+		printf(" %3s", st_shndx(sym.st_shndx));
+		if ((name = elf_strptr(re->elf, stab, sym.st_name)) != NULL)
+			printf(" %s", name);
+		/* Append symbol version string for SHT_DYNSYM symbol table. */
+		if (s->type == SHT_DYNSYM && re->ver != NULL &&
+		    re->vs != NULL && re->vs[j] > 1) {
+			vs = re->vs[j] & VERSYM_VERSION;
+			if (vs >= re->ver_sz || re->ver[vs].name == NULL) {
+				warnx("invalid versym version index %u", vs);
+				break;
+			}
+			if (re->vs[j] & VERSYM_HIDDEN || re->ver[vs].type == 0)
+				printf("@%s (%d)", re->ver[vs].name, vs);
+			else
+				printf("@@%s (%d)", re->ver[vs].name, vs);
+		}
+		putchar('\n');
+	}
+
+}
+
+static void
+dump_symtabs(struct readelf *re)
+{
+	GElf_Dyn dyn;
+	Elf_Data *d;
+	struct section *s;
+	uint64_t dyn_off;
+	int elferr, i, len;
+
+	/*
+	 * If -D is specified, only dump the symbol table specified by
+	 * the DT_SYMTAB entry in the .dynamic section.
+	 */
+	dyn_off = 0;
+	if (re->options & RE_DD) {
+		s = NULL;
+		for (i = 0; (size_t)i < re->shnum; i++)
+			if (re->sl[i].type == SHT_DYNAMIC) {
+				s = &re->sl[i];
+				break;
+			}
+		if (s == NULL)
+			return;
+		(void) elf_errno();
+		if ((d = elf_getdata(s->scn, NULL)) == NULL) {
+			elferr = elf_errno();
+			if (elferr != 0)
+				warnx("elf_getdata failed: %s", elf_errmsg(-1));
+			return;
+		}
+		if (d->d_size <= 0)
+			return;
+		if (!get_ent_count(s, &len))
+			return;
+
+		for (i = 0; i < len; i++) {
+			if (gelf_getdyn(d, i, &dyn) != &dyn) {
+				warnx("gelf_getdyn failed: %s", elf_errmsg(-1));
+				continue;
+			}
+			if (dyn.d_tag == DT_SYMTAB) {
+				dyn_off = dyn.d_un.d_val;
+				break;
+			}
+		}
+	}
+
+	/* Find and dump symbol tables. */
+	for (i = 0; (size_t)i < re->shnum; i++) {
+		s = &re->sl[i];
+		if (s->type == SHT_SYMTAB || s->type == SHT_DYNSYM) {
+			if (re->options & RE_DD) {
+				if (dyn_off == s->addr) {
+					dump_symtab(re, i);
+					break;
+				}
+			} else
+				dump_symtab(re, i);
+		}
+	}
+}
+
+static void
+dump_svr4_hash(struct section *s)
+{
+	Elf_Data	*d;
+	uint32_t	*buf;
+	uint32_t	 nbucket, nchain;
+	uint32_t	*bucket, *chain;
+	uint32_t	*bl, *c, maxl, total;
+	int		 elferr, i, j;
+
+	/* Read and parse the content of .hash section. */
+	(void) elf_errno();
+	if ((d = elf_getdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_getdata failed: %s", elf_errmsg(elferr));
+		return;
+	}
+	if (d->d_size < 2 * sizeof(uint32_t)) {
+		warnx(".hash section too small");
+		return;
+	}
+	buf = d->d_buf;
+	nbucket = buf[0];
+	nchain = buf[1];
+	if (nbucket <= 0 || nchain <= 0) {
+		warnx("Malformed .hash section");
+		return;
+	}
+	if (d->d_size != (nbucket + nchain + 2) * sizeof(uint32_t)) {
+		warnx("Malformed .hash section");
+		return;
+	}
+	bucket = &buf[2];
+	chain = &buf[2 + nbucket];
+
+	maxl = 0;
+	if ((bl = calloc(nbucket, sizeof(*bl))) == NULL)
+		errx(EXIT_FAILURE, "calloc failed");
+	for (i = 0; (uint32_t)i < nbucket; i++)
+		for (j = bucket[i]; j > 0 && (uint32_t)j < nchain; j = chain[j])
+			if (++bl[i] > maxl)
+				maxl = bl[i];
+	if ((c = calloc(maxl + 1, sizeof(*c))) == NULL)
+		errx(EXIT_FAILURE, "calloc failed");
+	for (i = 0; (uint32_t)i < nbucket; i++)
+		c[bl[i]]++;
+	printf("\nHistogram for bucket list length (total of %u buckets):\n",
+	    nbucket);
+	printf(" Length\tNumber\t\t%% of total\tCoverage\n");
+	total = 0;
+	for (i = 0; (uint32_t)i <= maxl; i++) {
+		total += c[i] * i;
+		printf("%7u\t%-10u\t(%5.1f%%)\t%5.1f%%\n", i, c[i],
+		    c[i] * 100.0 / nbucket, total * 100.0 / (nchain - 1));
+	}
+	free(c);
+	free(bl);
+}
+
+static void
+dump_svr4_hash64(struct readelf *re, struct section *s)
+{
+	Elf_Data	*d, dst;
+	uint64_t	*buf;
+	uint64_t	 nbucket, nchain;
+	uint64_t	*bucket, *chain;
+	uint64_t	*bl, *c, maxl, total;
+	int		 elferr, i, j;
+
+	/*
+	 * ALPHA uses 64-bit hash entries. Since libelf assumes that
+	 * .hash section contains only 32-bit entry, an explicit
+	 * gelf_xlatetom is needed here.
+	 */
+	(void) elf_errno();
+	if ((d = elf_rawdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_rawdata failed: %s",
+			    elf_errmsg(elferr));
+		return;
+	}
+	d->d_type = ELF_T_XWORD;
+	memcpy(&dst, d, sizeof(Elf_Data));
+	if (gelf_xlatetom(re->elf, &dst, d,
+		re->ehdr.e_ident[EI_DATA]) != &dst) {
+		warnx("gelf_xlatetom failed: %s", elf_errmsg(-1));
+		return;
+	}
+	if (dst.d_size < 2 * sizeof(uint64_t)) {
+		warnx(".hash section too small");
+		return;
+	}
+	buf = dst.d_buf;
+	nbucket = buf[0];
+	nchain = buf[1];
+	if (nbucket <= 0 || nchain <= 0) {
+		warnx("Malformed .hash section");
+		return;
+	}
+	if (d->d_size != (nbucket + nchain + 2) * sizeof(uint32_t)) {
+		warnx("Malformed .hash section");
+		return;
+	}
+	bucket = &buf[2];
+	chain = &buf[2 + nbucket];
+
+	maxl = 0;
+	if ((bl = calloc(nbucket, sizeof(*bl))) == NULL)
+		errx(EXIT_FAILURE, "calloc failed");
+	for (i = 0; (uint32_t)i < nbucket; i++)
+		for (j = bucket[i]; j > 0 && (uint32_t)j < nchain; j = chain[j])
+			if (++bl[i] > maxl)
+				maxl = bl[i];
+	if ((c = calloc(maxl + 1, sizeof(*c))) == NULL)
+		errx(EXIT_FAILURE, "calloc failed");
+	for (i = 0; (uint64_t)i < nbucket; i++)
+		c[bl[i]]++;
+	printf("Histogram for bucket list length (total of %ju buckets):\n",
+	    (uintmax_t)nbucket);
+	printf(" Length\tNumber\t\t%% of total\tCoverage\n");
+	total = 0;
+	for (i = 0; (uint64_t)i <= maxl; i++) {
+		total += c[i] * i;
+		printf("%7u\t%-10ju\t(%5.1f%%)\t%5.1f%%\n", i, (uintmax_t)c[i],
+		    c[i] * 100.0 / nbucket, total * 100.0 / (nchain - 1));
+	}
+	free(c);
+	free(bl);
+}
+
+static void
+dump_gnu_hash(struct readelf *re, struct section *s)
+{
+	struct section	*ds;
+	Elf_Data	*d;
+	uint32_t	*buf;
+	uint32_t	*bucket, *chain;
+	uint32_t	 nbucket, nchain, symndx, maskwords;
+	uint32_t	*bl, *c, maxl, total;
+	int		 elferr, dynsymcount, i, j;
+
+	(void) elf_errno();
+	if ((d = elf_getdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_getdata failed: %s",
+			    elf_errmsg(elferr));
+		return;
+	}
+	if (d->d_size < 4 * sizeof(uint32_t)) {
+		warnx(".gnu.hash section too small");
+		return;
+	}
+	buf = d->d_buf;
+	nbucket = buf[0];
+	symndx = buf[1];
+	maskwords = buf[2];
+	buf += 4;
+	if (s->link >= re->shnum)
+		return;
+	ds = &re->sl[s->link];
+	if (!get_ent_count(ds, &dynsymcount))
+		return;
+	if (symndx >= (uint32_t)dynsymcount) {
+		warnx("Malformed .gnu.hash section (symndx out of range)");
+		return;
+	}
+	nchain = dynsymcount - symndx;
+	if (d->d_size != 4 * sizeof(uint32_t) + maskwords *
+	    (re->ec == ELFCLASS32 ? sizeof(uint32_t) : sizeof(uint64_t)) +
+	    (nbucket + nchain) * sizeof(uint32_t)) {
+		warnx("Malformed .gnu.hash section");
+		return;
+	}
+	bucket = buf + (re->ec == ELFCLASS32 ? maskwords : maskwords * 2);
+	chain = bucket + nbucket;
+
+	maxl = 0;
+	if ((bl = calloc(nbucket, sizeof(*bl))) == NULL)
+		errx(EXIT_FAILURE, "calloc failed");
+	for (i = 0; (uint32_t)i < nbucket; i++)
+		for (j = bucket[i]; j > 0 && (uint32_t)j - symndx < nchain;
+		     j++) {
+			if (++bl[i] > maxl)
+				maxl = bl[i];
+			if (chain[j - symndx] & 1)
+				break;
+		}
+	if ((c = calloc(maxl + 1, sizeof(*c))) == NULL)
+		errx(EXIT_FAILURE, "calloc failed");
+	for (i = 0; (uint32_t)i < nbucket; i++)
+		c[bl[i]]++;
+	printf("Histogram for bucket list length (total of %u buckets):\n",
+	    nbucket);
+	printf(" Length\tNumber\t\t%% of total\tCoverage\n");
+	total = 0;
+	for (i = 0; (uint32_t)i <= maxl; i++) {
+		total += c[i] * i;
+		printf("%7u\t%-10u\t(%5.1f%%)\t%5.1f%%\n", i, c[i],
+		    c[i] * 100.0 / nbucket, total * 100.0 / (nchain - 1));
+	}
+	free(c);
+	free(bl);
+}
+
+static void
+dump_hash(struct readelf *re)
+{
+	struct section	*s;
+	int		 i;
+
+	for (i = 0; (size_t) i < re->shnum; i++) {
+		s = &re->sl[i];
+		if (s->type == SHT_HASH || s->type == SHT_GNU_HASH) {
+			if (s->type == SHT_GNU_HASH)
+				dump_gnu_hash(re, s);
+			else if (re->ehdr.e_machine == EM_ALPHA &&
+			    s->entsize == 8)
+				dump_svr4_hash64(re, s);
+			else
+				dump_svr4_hash(s);
+		}
+	}
+}
+
+static void
+dump_notes(struct readelf *re)
+{
+	struct section *s;
+	const char *rawfile;
+	GElf_Phdr phdr;
+	Elf_Data *d;
+	size_t filesize, phnum;
+	int i, elferr;
+
+	if (re->ehdr.e_type == ET_CORE) {
+		/*
+		 * Search program headers in the core file for
+		 * PT_NOTE entry.
+		 */
+		if (elf_getphnum(re->elf, &phnum) == 0) {
+			warnx("elf_getphnum failed: %s", elf_errmsg(-1));
+			return;
+		}
+		if (phnum == 0)
+			return;
+		if ((rawfile = elf_rawfile(re->elf, &filesize)) == NULL) {
+			warnx("elf_rawfile failed: %s", elf_errmsg(-1));
+			return;
+		}
+		for (i = 0; (size_t) i < phnum; i++) {
+			if (gelf_getphdr(re->elf, i, &phdr) != &phdr) {
+				warnx("gelf_getphdr failed: %s",
+				    elf_errmsg(-1));
+				continue;
+			}
+			if (phdr.p_type == PT_NOTE) {
+				if (phdr.p_offset >= filesize ||
+				    phdr.p_filesz > filesize - phdr.p_offset) {
+					warnx("invalid PHDR offset");
+					continue;
+				}
+				dump_notes_content(re, rawfile + phdr.p_offset,
+				    phdr.p_filesz, phdr.p_offset);
+			}
+		}
+
+	} else {
+		/*
+		 * For objects other than core files, Search for
+		 * SHT_NOTE sections.
+		 */
+		for (i = 0; (size_t) i < re->shnum; i++) {
+			s = &re->sl[i];
+			if (s->type == SHT_NOTE) {
+				(void) elf_errno();
+				if ((d = elf_getdata(s->scn, NULL)) == NULL) {
+					elferr = elf_errno();
+					if (elferr != 0)
+						warnx("elf_getdata failed: %s",
+						    elf_errmsg(elferr));
+					continue;
+				}
+				dump_notes_content(re, d->d_buf, d->d_size,
+				    s->off);
+			}
+		}
+	}
+}
+
+static void
+dump_notes_content(struct readelf *re, const char *buf, size_t sz, off_t off)
+{
+	Elf_Note *note;
+	const char *end, *name;
+
+	printf("\nNotes at offset %#010jx with length %#010jx:\n",
+	    (uintmax_t) off, (uintmax_t) sz);
+	printf("  %-13s %-15s %s\n", "Owner", "Data size", "Description");
+	end = buf + sz;
+	while (buf < end) {
+		if (buf + sizeof(*note) > end) {
+			warnx("invalid note header");
+			return;
+		}
+		note = (Elf_Note *)(uintptr_t) buf;
+		name = (char *)(uintptr_t)(note + 1);
+		/*
+		 * The name field is required to be nul-terminated, and
+		 * n_namesz includes the terminating nul in observed
+		 * implementations (contrary to the ELF-64 spec). A special
+		 * case is needed for cores generated by some older Linux
+		 * versions, which write a note named "CORE" without a nul
+		 * terminator and n_namesz = 4.
+		 */
+		if (note->n_namesz == 0)
+			name = "";
+		else if (note->n_namesz == 4 && strncmp(name, "CORE", 4) == 0)
+			name = "CORE";
+		else if (strnlen(name, note->n_namesz) >= note->n_namesz)
+			name = "<invalid>";
+		printf("  %-13s %#010jx", name, (uintmax_t) note->n_descsz);
+		printf("      %s\n", note_type(name, re->ehdr.e_type,
+		    note->n_type));
+		buf += sizeof(Elf_Note) + roundup2(note->n_namesz, 4) +
+		    roundup2(note->n_descsz, 4);
+	}
+}
+
+/*
+ * Symbol versioning sections are the same for 32bit and 64bit
+ * ELF objects.
+ */
+#define Elf_Verdef	Elf32_Verdef
+#define	Elf_Verdaux	Elf32_Verdaux
+#define	Elf_Verneed	Elf32_Verneed
+#define	Elf_Vernaux	Elf32_Vernaux
+
+#define	SAVE_VERSION_NAME(x, n, t)					\
+	do {								\
+		while (x >= re->ver_sz) {				\
+			nv = realloc(re->ver,				\
+			    sizeof(*re->ver) * re->ver_sz * 2);		\
+			if (nv == NULL) {				\
+				warn("realloc failed");			\
+				free(re->ver);				\
+				return;					\
+			}						\
+			re->ver = nv;					\
+			for (i = re->ver_sz; i < re->ver_sz * 2; i++) {	\
+				re->ver[i].name = NULL;			\
+				re->ver[i].type = 0;			\
+			}						\
+			re->ver_sz *= 2;				\
+		}							\
+		if (x > 1) {						\
+			re->ver[x].name = n;				\
+			re->ver[x].type = t;				\
+		}							\
+	} while (0)
+
+
+static void
+dump_verdef(struct readelf *re, int dump)
+{
+	struct section *s;
+	struct symver *nv;
+	Elf_Data *d;
+	Elf_Verdef *vd;
+	Elf_Verdaux *vda;
+	uint8_t *buf, *end, *buf2;
+	const char *name;
+	int elferr, i, j;
+
+	if ((s = re->vd_s) == NULL)
+		return;
+	if (s->link >= re->shnum)
+		return;
+
+	if (re->ver == NULL) {
+		re->ver_sz = 16;
+		if ((re->ver = calloc(re->ver_sz, sizeof(*re->ver))) ==
+		    NULL) {
+			warn("calloc failed");
+			return;
+		}
+		re->ver[0].name = "*local*";
+		re->ver[1].name = "*global*";
+	}
+
+	if (dump)
+		printf("\nVersion definition section (%s):\n", s->name);
+	(void) elf_errno();
+	if ((d = elf_getdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_getdata failed: %s", elf_errmsg(elferr));
+		return;
+	}
+	if (d->d_size == 0)
+		return;
+
+	buf = d->d_buf;
+	end = buf + d->d_size;
+	while (buf + sizeof(Elf_Verdef) <= end) {
+		vd = (Elf_Verdef *) (uintptr_t) buf;
+		if (dump) {
+			printf("  0x%4.4lx", (unsigned long)
+			    (buf - (uint8_t *)d->d_buf));
+			printf(" vd_version: %u vd_flags: %d"
+			    " vd_ndx: %u vd_cnt: %u", vd->vd_version,
+			    vd->vd_flags, vd->vd_ndx, vd->vd_cnt);
+		}
+		buf2 = buf + vd->vd_aux;
+		j = 0;
+		while (buf2 + sizeof(Elf_Verdaux) <= end && j < vd->vd_cnt) {
+			vda = (Elf_Verdaux *) (uintptr_t) buf2;
+			name = get_string(re, s->link, vda->vda_name);
+			if (j == 0) {
+				if (dump)
+					printf(" vda_name: %s\n", name);
+				SAVE_VERSION_NAME((int)vd->vd_ndx, name, 1);
+			} else if (dump)
+				printf("  0x%4.4lx parent: %s\n",
+				    (unsigned long) (buf2 -
+				    (uint8_t *)d->d_buf), name);
+			if (vda->vda_next == 0)
+				break;
+			buf2 += vda->vda_next;
+			j++;
+		}
+		if (vd->vd_next == 0)
+			break;
+		buf += vd->vd_next;
+	}
+}
+
+static void
+dump_verneed(struct readelf *re, int dump)
+{
+	struct section *s;
+	struct symver *nv;
+	Elf_Data *d;
+	Elf_Verneed *vn;
+	Elf_Vernaux *vna;
+	uint8_t *buf, *end, *buf2;
+	const char *name;
+	int elferr, i, j;
+
+	if ((s = re->vn_s) == NULL)
+		return;
+	if (s->link >= re->shnum)
+		return;
+
+	if (re->ver == NULL) {
+		re->ver_sz = 16;
+		if ((re->ver = calloc(re->ver_sz, sizeof(*re->ver))) ==
+		    NULL) {
+			warn("calloc failed");
+			return;
+		}
+		re->ver[0].name = "*local*";
+		re->ver[1].name = "*global*";
+	}
+
+	if (dump)
+		printf("\nVersion needed section (%s):\n", s->name);
+	(void) elf_errno();
+	if ((d = elf_getdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_getdata failed: %s", elf_errmsg(elferr));
+		return;
+	}
+	if (d->d_size == 0)
+		return;
+
+	buf = d->d_buf;
+	end = buf + d->d_size;
+	while (buf + sizeof(Elf_Verneed) <= end) {
+		vn = (Elf_Verneed *) (uintptr_t) buf;
+		if (dump) {
+			printf("  0x%4.4lx", (unsigned long)
+			    (buf - (uint8_t *)d->d_buf));
+			printf(" vn_version: %u vn_file: %s vn_cnt: %u\n",
+			    vn->vn_version,
+			    get_string(re, s->link, vn->vn_file),
+			    vn->vn_cnt);
+		}
+		buf2 = buf + vn->vn_aux;
+		j = 0;
+		while (buf2 + sizeof(Elf_Vernaux) <= end && j < vn->vn_cnt) {
+			vna = (Elf32_Vernaux *) (uintptr_t) buf2;
+			if (dump)
+				printf("  0x%4.4lx", (unsigned long)
+				    (buf2 - (uint8_t *)d->d_buf));
+			name = get_string(re, s->link, vna->vna_name);
+			if (dump)
+				printf("   vna_name: %s vna_flags: %u"
+				    " vna_other: %u\n", name,
+				    vna->vna_flags, vna->vna_other);
+			SAVE_VERSION_NAME((int)vna->vna_other, name, 0);
+			if (vna->vna_next == 0)
+				break;
+			buf2 += vna->vna_next;
+			j++;
+		}
+		if (vn->vn_next == 0)
+			break;
+		buf += vn->vn_next;
+	}
+}
+
+static void
+dump_versym(struct readelf *re)
+{
+	int i;
+	uint16_t vs;
+
+	if (re->vs_s == NULL || re->ver == NULL || re->vs == NULL)
+		return;
+	printf("\nVersion symbol section (%s):\n", re->vs_s->name);
+	for (i = 0; i < re->vs_sz; i++) {
+		if ((i & 3) == 0) {
+			if (i > 0)
+				putchar('\n');
+			printf("  %03x:", i);
+		}
+		vs = re->vs[i] & VERSYM_VERSION;
+		if (vs >= re->ver_sz || re->ver[vs].name == NULL) {
+			warnx("invalid versym version index %u", re->vs[i]);
+			break;
+		}
+		if (re->vs[i] & VERSYM_HIDDEN)
+			printf(" %3xh %-12s ", vs,
+			    re->ver[re->vs[i] & VERSYM_VERSION].name);
+		else
+			printf(" %3x %-12s ", vs, re->ver[re->vs[i]].name);
+	}
+	putchar('\n');
+}
+
+static void
+dump_ver(struct readelf *re)
+{
+
+	if (re->vs_s && re->ver && re->vs)
+		dump_versym(re);
+	if (re->vd_s)
+		dump_verdef(re, 1);
+	if (re->vn_s)
+		dump_verneed(re, 1);
+}
+
+static void
+search_ver(struct readelf *re)
+{
+	struct section *s;
+	Elf_Data *d;
+	int elferr, i;
+
+	for (i = 0; (size_t) i < re->shnum; i++) {
+		s = &re->sl[i];
+		if (s->type == SHT_SUNW_versym)
+			re->vs_s = s;
+		if (s->type == SHT_SUNW_verneed)
+			re->vn_s = s;
+		if (s->type == SHT_SUNW_verdef)
+			re->vd_s = s;
+	}
+	if (re->vd_s)
+		dump_verdef(re, 0);
+	if (re->vn_s)
+		dump_verneed(re, 0);
+	if (re->vs_s && re->ver != NULL) {
+		(void) elf_errno();
+		if ((d = elf_getdata(re->vs_s->scn, NULL)) == NULL) {
+			elferr = elf_errno();
+			if (elferr != 0)
+				warnx("elf_getdata failed: %s",
+				    elf_errmsg(elferr));
+			return;
+		}
+		if (d->d_size == 0)
+			return;
+		re->vs = d->d_buf;
+		re->vs_sz = d->d_size / sizeof(Elf32_Half);
+	}
+}
+
+#undef	Elf_Verdef
+#undef	Elf_Verdaux
+#undef	Elf_Verneed
+#undef	Elf_Vernaux
+#undef	SAVE_VERSION_NAME
+
+/*
+ * Elf32_Lib and Elf64_Lib are identical.
+ */
+#define	Elf_Lib		Elf32_Lib
+
+static void
+dump_liblist(struct readelf *re)
+{
+	struct section *s;
+	struct tm *t;
+	time_t ti;
+	char tbuf[20];
+	Elf_Data *d;
+	Elf_Lib *lib;
+	int i, j, k, elferr, first, len;
+
+	for (i = 0; (size_t) i < re->shnum; i++) {
+		s = &re->sl[i];
+		if (s->type != SHT_GNU_LIBLIST)
+			continue;
+		if (s->link >= re->shnum)
+			continue;
+		(void) elf_errno();
+		if ((d = elf_getdata(s->scn, NULL)) == NULL) {
+			elferr = elf_errno();
+			if (elferr != 0)
+				warnx("elf_getdata failed: %s",
+				    elf_errmsg(elferr));
+			continue;
+		}
+		if (d->d_size <= 0)
+			continue;
+		lib = d->d_buf;
+		if (!get_ent_count(s, &len))
+			continue;
+		printf("\nLibrary list section '%s' ", s->name);
+		printf("contains %d entries:\n", len);
+		printf("%12s%24s%18s%10s%6s\n", "Library", "Time Stamp",
+		    "Checksum", "Version", "Flags");
+		for (j = 0; (uint64_t) j < s->sz / s->entsize; j++) {
+			printf("%3d: ", j);
+			printf("%-20.20s ",
+			    get_string(re, s->link, lib->l_name));
+			ti = lib->l_time_stamp;
+			t = gmtime(&ti);
+			snprintf(tbuf, sizeof(tbuf), "%04d-%02d-%02dT%02d:%02d"
+			    ":%2d", t->tm_year + 1900, t->tm_mon + 1,
+			    t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
+			printf("%-19.19s ", tbuf);
+			printf("0x%08x ", lib->l_checksum);
+			printf("%-7d %#x", lib->l_version, lib->l_flags);
+			if (lib->l_flags != 0) {
+				first = 1;
+				putchar('(');
+				for (k = 0; l_flag[k].name != NULL; k++) {
+					if ((l_flag[k].value & lib->l_flags) ==
+					    0)
+						continue;
+					if (!first)
+						putchar(',');
+					else
+						first = 0;
+					printf("%s", l_flag[k].name);
+				}
+				putchar(')');
+			}
+			putchar('\n');
+			lib++;
+		}
+	}
+}
+
+#undef Elf_Lib
+
+static void
+dump_section_groups(struct readelf *re)
+{
+	struct section *s;
+	const char *symname;
+	Elf_Data *d;
+	uint32_t *w;
+	int i, j, elferr;
+	size_t n;
+
+	for (i = 0; (size_t) i < re->shnum; i++) {
+		s = &re->sl[i];
+		if (s->type != SHT_GROUP)
+			continue;
+		if (s->link >= re->shnum)
+			continue;
+		(void) elf_errno();
+		if ((d = elf_getdata(s->scn, NULL)) == NULL) {
+			elferr = elf_errno();
+			if (elferr != 0)
+				warnx("elf_getdata failed: %s",
+				    elf_errmsg(elferr));
+			continue;
+		}
+		if (d->d_size <= 0)
+			continue;
+
+		w = d->d_buf;
+
+		/* We only support COMDAT section. */
+#ifndef GRP_COMDAT
+#define	GRP_COMDAT 0x1
+#endif
+		if ((*w++ & GRP_COMDAT) == 0)
+			return;
+
+		if (s->entsize == 0)
+			s->entsize = 4;
+
+		symname = get_symbol_name(re, s->link, s->info);
+		n = s->sz / s->entsize;
+		if (n-- < 1)
+			return;
+
+		printf("\nCOMDAT group section [%5d] `%s' [%s] contains %ju"
+		    " sections:\n", i, s->name, symname, (uintmax_t)n);
+		printf("   %-10.10s %s\n", "[Index]", "Name");
+		for (j = 0; (size_t) j < n; j++, w++) {
+			if (*w >= re->shnum) {
+				warnx("invalid section index: %u", *w);
+				continue;
+			}
+			printf("   [%5u]   %s\n", *w, re->sl[*w].name);
+		}
+	}
+}
+
+static uint8_t *
+dump_unknown_tag(uint64_t tag, uint8_t *p, uint8_t *pe)
+{
+	uint64_t val;
+
+	/*
+	 * According to ARM EABI: For tags > 32, even numbered tags have
+	 * a ULEB128 param and odd numbered ones have NUL-terminated
+	 * string param. This rule probably also applies for tags <= 32
+	 * if the object arch is not ARM.
+	 */
+
+	printf("  Tag_unknown_%ju: ", (uintmax_t) tag);
+
+	if (tag & 1) {
+		printf("%s\n", (char *) p);
+		p += strlen((char *) p) + 1;
+	} else {
+		val = _decode_uleb128(&p, pe);
+		printf("%ju\n", (uintmax_t) val);
+	}
+
+	return (p);
+}
+
+static uint8_t *
+dump_compatibility_tag(uint8_t *p, uint8_t *pe)
+{
+	uint64_t val;
+
+	val = _decode_uleb128(&p, pe);
+	printf("flag = %ju, vendor = %s\n", (uintmax_t) val, p);
+	p += strlen((char *) p) + 1;
+
+	return (p);
+}
+
+static void
+dump_arm_attributes(struct readelf *re, uint8_t *p, uint8_t *pe)
+{
+	uint64_t tag, val;
+	size_t i;
+	int found, desc;
+
+	(void) re;
+
+	while (p < pe) {
+		tag = _decode_uleb128(&p, pe);
+		found = desc = 0;
+		for (i = 0; i < sizeof(aeabi_tags) / sizeof(aeabi_tags[0]);
+		     i++) {
+			if (tag == aeabi_tags[i].tag) {
+				found = 1;
+				printf("  %s: ", aeabi_tags[i].s_tag);
+				if (aeabi_tags[i].get_desc) {
+					desc = 1;
+					val = _decode_uleb128(&p, pe);
+					printf("%s\n",
+					    aeabi_tags[i].get_desc(val));
+				}
+				break;
+			}
+			if (tag < aeabi_tags[i].tag)
+				break;
+		}
+		if (!found) {
+			p = dump_unknown_tag(tag, p, pe);
+			continue;
+		}
+		if (desc)
+			continue;
+
+		switch (tag) {
+		case 4:		/* Tag_CPU_raw_name */
+		case 5:		/* Tag_CPU_name */
+		case 67:	/* Tag_conformance */
+			printf("%s\n", (char *) p);
+			p += strlen((char *) p) + 1;
+			break;
+		case 32:	/* Tag_compatibility */
+			p = dump_compatibility_tag(p, pe);
+			break;
+		case 64:	/* Tag_nodefaults */
+			/* ignored, written as 0. */
+			(void) _decode_uleb128(&p, pe);
+			printf("True\n");
+			break;
+		case 65:	/* Tag_also_compatible_with */
+			val = _decode_uleb128(&p, pe);
+			/* Must be Tag_CPU_arch */
+			if (val != 6) {
+				printf("unknown\n");
+				break;
+			}
+			val = _decode_uleb128(&p, pe);
+			printf("%s\n", aeabi_cpu_arch(val));
+			/* Skip NUL terminator. */
+			p++;
+			break;
+		default:
+			putchar('\n');
+			break;
+		}
+	}
+}
+
+#ifndef	Tag_GNU_MIPS_ABI_FP
+#define	Tag_GNU_MIPS_ABI_FP	4
+#endif
+
+static void
+dump_mips_attributes(struct readelf *re, uint8_t *p, uint8_t *pe)
+{
+	uint64_t tag, val;
+
+	(void) re;
+
+	while (p < pe) {
+		tag = _decode_uleb128(&p, pe);
+		switch (tag) {
+		case Tag_GNU_MIPS_ABI_FP:
+			val = _decode_uleb128(&p, pe);
+			printf("  Tag_GNU_MIPS_ABI_FP: %s\n", mips_abi_fp(val));
+			break;
+		case 32:	/* Tag_compatibility */
+			p = dump_compatibility_tag(p, pe);
+			break;
+		default:
+			p = dump_unknown_tag(tag, p, pe);
+			break;
+		}
+	}
+}
+
+#ifndef Tag_GNU_Power_ABI_FP
+#define	Tag_GNU_Power_ABI_FP	4
+#endif
+
+#ifndef Tag_GNU_Power_ABI_Vector
+#define	Tag_GNU_Power_ABI_Vector	8
+#endif
+
+static void
+dump_ppc_attributes(uint8_t *p, uint8_t *pe)
+{
+	uint64_t tag, val;
+
+	while (p < pe) {
+		tag = _decode_uleb128(&p, pe);
+		switch (tag) {
+		case Tag_GNU_Power_ABI_FP:
+			val = _decode_uleb128(&p, pe);
+			printf("  Tag_GNU_Power_ABI_FP: %s\n", ppc_abi_fp(val));
+			break;
+		case Tag_GNU_Power_ABI_Vector:
+			val = _decode_uleb128(&p, pe);
+			printf("  Tag_GNU_Power_ABI_Vector: %s\n",
+			    ppc_abi_vector(val));
+			break;
+		case 32:	/* Tag_compatibility */
+			p = dump_compatibility_tag(p, pe);
+			break;
+		default:
+			p = dump_unknown_tag(tag, p, pe);
+			break;
+		}
+	}
+}
+
+static void
+dump_attributes(struct readelf *re)
+{
+	struct section *s;
+	Elf_Data *d;
+	uint8_t *p, *pe, *sp;
+	size_t len, seclen, nlen, sublen;
+	uint64_t val;
+	int tag, i, elferr;
+
+	for (i = 0; (size_t) i < re->shnum; i++) {
+		s = &re->sl[i];
+		if (s->type != SHT_GNU_ATTRIBUTES &&
+		    (re->ehdr.e_machine != EM_ARM || s->type != SHT_LOPROC + 3))
+			continue;
+		(void) elf_errno();
+		if ((d = elf_rawdata(s->scn, NULL)) == NULL) {
+			elferr = elf_errno();
+			if (elferr != 0)
+				warnx("elf_rawdata failed: %s",
+				    elf_errmsg(elferr));
+			continue;
+		}
+		if (d->d_size <= 0)
+			continue;
+		p = d->d_buf;
+		pe = p + d->d_size;
+		if (*p != 'A') {
+			printf("Unknown Attribute Section Format: %c\n",
+			    (char) *p);
+			continue;
+		}
+		len = d->d_size - 1;
+		p++;
+		while (len > 0) {
+			if (len < 4) {
+				warnx("truncated attribute section length");
+				return;
+			}
+			seclen = re->dw_decode(&p, 4);
+			if (seclen > len) {
+				warnx("invalid attribute section length");
+				return;
+			}
+			len -= seclen;
+			nlen = strlen((char *) p) + 1;
+			if (nlen + 4 > seclen) {
+				warnx("invalid attribute section name");
+				return;
+			}
+			printf("Attribute Section: %s\n", (char *) p);
+			p += nlen;
+			seclen -= nlen + 4;
+			while (seclen > 0) {
+				sp = p;
+				tag = *p++;
+				sublen = re->dw_decode(&p, 4);
+				if (sublen > seclen) {
+					warnx("invalid attribute sub-section"
+					    " length");
+					return;
+				}
+				seclen -= sublen;
+				printf("%s", top_tag(tag));
+				if (tag == 2 || tag == 3) {
+					putchar(':');
+					for (;;) {
+						val = _decode_uleb128(&p, pe);
+						if (val == 0)
+							break;
+						printf(" %ju", (uintmax_t) val);
+					}
+				}
+				putchar('\n');
+				if (re->ehdr.e_machine == EM_ARM &&
+				    s->type == SHT_LOPROC + 3)
+					dump_arm_attributes(re, p, sp + sublen);
+				else if (re->ehdr.e_machine == EM_MIPS ||
+				    re->ehdr.e_machine == EM_MIPS_RS3_LE)
+					dump_mips_attributes(re, p,
+					    sp + sublen);
+				else if (re->ehdr.e_machine == EM_PPC)
+					dump_ppc_attributes(p, sp + sublen);
+				p = sp + sublen;
+			}
+		}
+	}
+}
+
+static void
+dump_mips_specific_info(struct readelf *re)
+{
+	struct section *s;
+	int i;
+
+	s = NULL;
+	for (i = 0; (size_t) i < re->shnum; i++) {
+		s = &re->sl[i];
+		if (s->name != NULL && (!strcmp(s->name, ".MIPS.options") ||
+		    (s->type == SHT_MIPS_OPTIONS))) {
+			dump_mips_options(re, s);
+		}
+	}
+
+	if (s->name != NULL && (!strcmp(s->name, ".MIPS.abiflags") ||
+	    (s->type == SHT_MIPS_ABIFLAGS)))
+		dump_mips_abiflags(re, s);
+
+	/*
+	 * Dump .reginfo if present (although it will be ignored by an OS if a
+	 * .MIPS.options section is present, according to SGI mips64 spec).
+	 */
+	for (i = 0; (size_t) i < re->shnum; i++) {
+		s = &re->sl[i];
+		if (s->name != NULL && (!strcmp(s->name, ".reginfo") ||
+		    (s->type == SHT_MIPS_REGINFO)))
+			dump_mips_reginfo(re, s);
+	}
+}
+
+static void
+dump_mips_abiflags(struct readelf *re, struct section *s)
+{
+	Elf_Data *d;
+	uint8_t *p;
+	int elferr;
+	uint32_t isa_ext, ases, flags1, flags2;
+	uint16_t version;
+	uint8_t isa_level, isa_rev, gpr_size, cpr1_size, cpr2_size, fp_abi;
+
+	if ((d = elf_rawdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_rawdata failed: %s",
+			    elf_errmsg(elferr));
+		return;
+	}
+	if (d->d_size != 24) {
+		warnx("invalid MIPS abiflags section size");
+		return;
+	}
+
+	p = d->d_buf;
+	version = re->dw_decode(&p, 2);
+	printf("MIPS ABI Flags Version: %u", version);
+	if (version != 0) {
+		printf(" (unknown)\n\n");
+		return;
+	}
+	printf("\n\n");
+
+	isa_level = re->dw_decode(&p, 1);
+	isa_rev = re->dw_decode(&p, 1);
+	gpr_size = re->dw_decode(&p, 1);
+	cpr1_size = re->dw_decode(&p, 1);
+	cpr2_size = re->dw_decode(&p, 1);
+	fp_abi = re->dw_decode(&p, 1);
+	isa_ext = re->dw_decode(&p, 4);
+	ases = re->dw_decode(&p, 4);
+	flags1 = re->dw_decode(&p, 4);
+	flags2 = re->dw_decode(&p, 4);
+
+	printf("ISA: ");
+	if (isa_rev <= 1)
+		printf("MIPS%u\n", isa_level);
+	else
+		printf("MIPS%ur%u\n", isa_level, isa_rev);
+	printf("GPR size: %d\n", get_mips_register_size(gpr_size));
+	printf("CPR1 size: %d\n", get_mips_register_size(cpr1_size));
+	printf("CPR2 size: %d\n", get_mips_register_size(cpr2_size));
+	printf("FP ABI: ");
+	switch (fp_abi) {
+	case 3:
+		printf("Soft float");
+		break;
+	default:
+		printf("%u", fp_abi);
+		break;
+	}
+	printf("\nISA Extension: %u\n", isa_ext);
+	printf("ASEs: %u\n", ases);
+	printf("FLAGS 1: %08x\n", flags1);
+	printf("FLAGS 2: %08x\n", flags2);
+}
+
+static int
+get_mips_register_size(uint8_t flag)
+{
+	switch (flag) {
+	case 0: return 0;
+	case 1: return 32;
+	case 2: return 64;
+	case 3: return 128;
+	default: return -1;
+	}
+}
+static void
+dump_mips_reginfo(struct readelf *re, struct section *s)
+{
+	Elf_Data *d;
+	int elferr, len;
+
+	(void) elf_errno();
+	if ((d = elf_rawdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_rawdata failed: %s",
+			    elf_errmsg(elferr));
+		return;
+	}
+	if (d->d_size <= 0)
+		return;
+	if (!get_ent_count(s, &len))
+		return;
+
+	printf("\nSection '%s' contains %d entries:\n", s->name, len);
+	dump_mips_odk_reginfo(re, d->d_buf, d->d_size);
+}
+
+static void
+dump_mips_options(struct readelf *re, struct section *s)
+{
+	Elf_Data *d;
+	uint32_t info;
+	uint16_t sndx;
+	uint8_t *p, *pe;
+	uint8_t kind, size;
+	int elferr;
+
+	(void) elf_errno();
+	if ((d = elf_rawdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_rawdata failed: %s",
+			    elf_errmsg(elferr));
+		return;
+	}
+	if (d->d_size == 0)
+		return;
+
+	printf("\nSection %s contains:\n", s->name);
+	p = d->d_buf;
+	pe = p + d->d_size;
+	while (p < pe) {
+		if (pe - p < 8) {
+			warnx("Truncated MIPS option header");
+			return;
+		}
+		kind = re->dw_decode(&p, 1);
+		size = re->dw_decode(&p, 1);
+		sndx = re->dw_decode(&p, 2);
+		info = re->dw_decode(&p, 4);
+		if (size < 8 || size - 8 > pe - p) {
+			warnx("Malformed MIPS option header");
+			return;
+		}
+		size -= 8;
+		switch (kind) {
+		case ODK_REGINFO:
+			dump_mips_odk_reginfo(re, p, size);
+			break;
+		case ODK_EXCEPTIONS:
+			printf(" EXCEPTIONS FPU_MIN: %#x\n",
+			    info & OEX_FPU_MIN);
+			printf("%11.11s FPU_MAX: %#x\n", "",
+			    info & OEX_FPU_MAX);
+			dump_mips_option_flags("", mips_exceptions_option,
+			    info);
+			break;
+		case ODK_PAD:
+			printf(" %-10.10s section: %ju\n", "OPAD",
+			    (uintmax_t) sndx);
+			dump_mips_option_flags("", mips_pad_option, info);
+			break;
+		case ODK_HWPATCH:
+			dump_mips_option_flags("HWPATCH", mips_hwpatch_option,
+			    info);
+			break;
+		case ODK_HWAND:
+			dump_mips_option_flags("HWAND", mips_hwa_option, info);
+			break;
+		case ODK_HWOR:
+			dump_mips_option_flags("HWOR", mips_hwo_option, info);
+			break;
+		case ODK_FILL:
+			printf(" %-10.10s %#jx\n", "FILL", (uintmax_t) info);
+			break;
+		case ODK_TAGS:
+			printf(" %-10.10s\n", "TAGS");
+			break;
+		case ODK_GP_GROUP:
+			printf(" %-10.10s GP group number: %#x\n", "GP_GROUP",
+			    info & 0xFFFF);
+			if (info & 0x10000)
+				printf(" %-10.10s GP group is "
+				    "self-contained\n", "");
+			break;
+		case ODK_IDENT:
+			printf(" %-10.10s default GP group number: %#x\n",
+			    "IDENT", info & 0xFFFF);
+			if (info & 0x10000)
+				printf(" %-10.10s default GP group is "
+				    "self-contained\n", "");
+			break;
+		case ODK_PAGESIZE:
+			printf(" %-10.10s\n", "PAGESIZE");
+			break;
+		default:
+			break;
+		}
+		p += size;
+	}
+}
+
+static void
+dump_mips_option_flags(const char *name, struct mips_option *opt, uint64_t info)
+{
+	int first;
+
+	first = 1;
+	for (; opt->desc != NULL; opt++) {
+		if (info & opt->flag) {
+			printf(" %-10.10s %s\n", first ? name : "",
+			    opt->desc);
+			first = 0;
+		}
+	}
+}
+
+static void
+dump_mips_odk_reginfo(struct readelf *re, uint8_t *p, size_t sz)
+{
+	uint32_t ri_gprmask;
+	uint32_t ri_cprmask[4];
+	uint64_t ri_gp_value;
+	uint8_t *pe;
+	int i;
+
+	pe = p + sz;
+	while (p < pe) {
+		ri_gprmask = re->dw_decode(&p, 4);
+		/* Skip ri_pad padding field for mips64. */
+		if (re->ec == ELFCLASS64)
+			re->dw_decode(&p, 4);
+		for (i = 0; i < 4; i++)
+			ri_cprmask[i] = re->dw_decode(&p, 4);
+		if (re->ec == ELFCLASS32)
+			ri_gp_value = re->dw_decode(&p, 4);
+		else
+			ri_gp_value = re->dw_decode(&p, 8);
+		printf(" %s    ", option_kind(ODK_REGINFO));
+		printf("ri_gprmask:    0x%08jx\n", (uintmax_t) ri_gprmask);
+		for (i = 0; i < 4; i++)
+			printf("%11.11s ri_cprmask[%d]: 0x%08jx\n", "", i,
+			    (uintmax_t) ri_cprmask[i]);
+		printf("%12.12s", "");
+		printf("ri_gp_value:   %#jx\n", (uintmax_t) ri_gp_value);
+	}
+}
+
+static void
+dump_arch_specific_info(struct readelf *re)
+{
+
+	dump_liblist(re);
+	dump_attributes(re);
+
+	switch (re->ehdr.e_machine) {
+	case EM_MIPS:
+	case EM_MIPS_RS3_LE:
+		dump_mips_specific_info(re);
+	default:
+		break;
+	}
+}
+
+static const char *
+dwarf_regname(struct readelf *re, unsigned int num)
+{
+	static char rx[32];
+	const char *rn;
+
+	if ((rn = dwarf_reg(re->ehdr.e_machine, num)) != NULL)
+		return (rn);
+
+	snprintf(rx, sizeof(rx), "r%u", num);
+
+	return (rx);
+}
+
+static void
+dump_dwarf_line(struct readelf *re)
+{
+	struct section *s;
+	Dwarf_Die die;
+	Dwarf_Error de;
+	Dwarf_Half tag, version, pointer_size;
+	Dwarf_Unsigned offset, endoff, length, hdrlen, dirndx, mtime, fsize;
+	Dwarf_Small minlen, defstmt, lrange, opbase, oplen;
+	Elf_Data *d;
+	char *pn;
+	uint64_t address, file, line, column, isa, opsize, udelta;
+	int64_t sdelta;
+	uint8_t *p, *pe;
+	int8_t lbase;
+	int i, is_stmt, dwarf_size, elferr, ret;
+
+	printf("\nDump of debug contents of section .debug_line:\n");
+
+	s = NULL;
+	for (i = 0; (size_t) i < re->shnum; i++) {
+		s = &re->sl[i];
+		if (s->name != NULL && !strcmp(s->name, ".debug_line"))
+			break;
+	}
+	if ((size_t) i >= re->shnum)
+		return;
+
+	(void) elf_errno();
+	if ((d = elf_getdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_getdata failed: %s", elf_errmsg(-1));
+		return;
+	}
+	if (d->d_size <= 0)
+		return;
+
+	while ((ret = dwarf_next_cu_header(re->dbg, NULL, NULL, NULL, NULL,
+	    NULL, &de)) ==  DW_DLV_OK) {
+		die = NULL;
+		while (dwarf_siblingof(re->dbg, die, &die, &de) == DW_DLV_OK) {
+			if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
+				warnx("dwarf_tag failed: %s",
+				    dwarf_errmsg(de));
+				return;
+			}
+			/* XXX: What about DW_TAG_partial_unit? */
+			if (tag == DW_TAG_compile_unit)
+				break;
+		}
+		if (die == NULL) {
+			warnx("could not find DW_TAG_compile_unit die");
+			return;
+		}
+		if (dwarf_attrval_unsigned(die, DW_AT_stmt_list, &offset,
+		    &de) != DW_DLV_OK)
+			continue;
+
+		length = re->dw_read(d, &offset, 4);
+		if (length == 0xffffffff) {
+			dwarf_size = 8;
+			length = re->dw_read(d, &offset, 8);
+		} else
+			dwarf_size = 4;
+
+		if (length > d->d_size - offset) {
+			warnx("invalid .dwarf_line section");
+			continue;
+		}
+
+		endoff = offset + length;
+		pe = (uint8_t *) d->d_buf + endoff;
+		version = re->dw_read(d, &offset, 2);
+		hdrlen = re->dw_read(d, &offset, dwarf_size);
+		minlen = re->dw_read(d, &offset, 1);
+		defstmt = re->dw_read(d, &offset, 1);
+		lbase = re->dw_read(d, &offset, 1);
+		lrange = re->dw_read(d, &offset, 1);
+		opbase = re->dw_read(d, &offset, 1);
+
+		printf("\n");
+		printf("  Length:\t\t\t%ju\n", (uintmax_t) length);
+		printf("  DWARF version:\t\t%u\n", version);
+		printf("  Prologue Length:\t\t%ju\n", (uintmax_t) hdrlen);
+		printf("  Minimum Instruction Length:\t%u\n", minlen);
+		printf("  Initial value of 'is_stmt':\t%u\n", defstmt);
+		printf("  Line Base:\t\t\t%d\n", lbase);
+		printf("  Line Range:\t\t\t%u\n", lrange);
+		printf("  Opcode Base:\t\t\t%u\n", opbase);
+		(void) dwarf_get_address_size(re->dbg, &pointer_size, &de);
+		printf("  (Pointer size:\t\t%u)\n", pointer_size);
+
+		printf("\n");
+		printf(" Opcodes:\n");
+		for (i = 1; i < opbase; i++) {
+			oplen = re->dw_read(d, &offset, 1);
+			printf("  Opcode %d has %u args\n", i, oplen);
+		}
+
+		printf("\n");
+		printf(" The Directory Table:\n");
+		p = (uint8_t *) d->d_buf + offset;
+		while (*p != '\0') {
+			printf("  %s\n", (char *) p);
+			p += strlen((char *) p) + 1;
+		}
+
+		p++;
+		printf("\n");
+		printf(" The File Name Table:\n");
+		printf("  Entry\tDir\tTime\tSize\tName\n");
+		i = 0;
+		while (*p != '\0') {
+			i++;
+			pn = (char *) p;
+			p += strlen(pn) + 1;
+			dirndx = _decode_uleb128(&p, pe);
+			mtime = _decode_uleb128(&p, pe);
+			fsize = _decode_uleb128(&p, pe);
+			printf("  %d\t%ju\t%ju\t%ju\t%s\n", i,
+			    (uintmax_t) dirndx, (uintmax_t) mtime,
+			    (uintmax_t) fsize, pn);
+		}
+
+#define	RESET_REGISTERS						\
+	do {							\
+		address	       = 0;				\
+		file	       = 1;				\
+		line	       = 1;				\
+		column	       = 0;				\
+		is_stmt	       = defstmt;			\
+	} while(0)
+
+#define	LINE(x) (lbase + (((x) - opbase) % lrange))
+#define	ADDRESS(x) ((((x) - opbase) / lrange) * minlen)
+
+		p++;
+		printf("\n");
+		printf(" Line Number Statements:\n");
+
+		RESET_REGISTERS;
+
+		while (p < pe) {
+
+			if (*p == 0) {
+				/*
+				 * Extended Opcodes.
+				 */
+				p++;
+				opsize = _decode_uleb128(&p, pe);
+				printf("  Extended opcode %u: ", *p);
+				switch (*p) {
+				case DW_LNE_end_sequence:
+					p++;
+					RESET_REGISTERS;
+					printf("End of Sequence\n");
+					break;
+				case DW_LNE_set_address:
+					p++;
+					address = re->dw_decode(&p,
+					    pointer_size);
+					printf("set Address to %#jx\n",
+					    (uintmax_t) address);
+					break;
+				case DW_LNE_define_file:
+					p++;
+					pn = (char *) p;
+					p += strlen(pn) + 1;
+					dirndx = _decode_uleb128(&p, pe);
+					mtime = _decode_uleb128(&p, pe);
+					fsize = _decode_uleb128(&p, pe);
+					printf("define new file: %s\n", pn);
+					break;
+				default:
+					/* Unrecognized extened opcodes. */
+					p += opsize;
+					printf("unknown opcode\n");
+				}
+			} else if (*p > 0 && *p < opbase) {
+				/*
+				 * Standard Opcodes.
+				 */
+				switch(*p++) {
+				case DW_LNS_copy:
+					printf("  Copy\n");
+					break;
+				case DW_LNS_advance_pc:
+					udelta = _decode_uleb128(&p, pe) *
+					    minlen;
+					address += udelta;
+					printf("  Advance PC by %ju to %#jx\n",
+					    (uintmax_t) udelta,
+					    (uintmax_t) address);
+					break;
+				case DW_LNS_advance_line:
+					sdelta = _decode_sleb128(&p, pe);
+					line += sdelta;
+					printf("  Advance Line by %jd to %ju\n",
+					    (intmax_t) sdelta,
+					    (uintmax_t) line);
+					break;
+				case DW_LNS_set_file:
+					file = _decode_uleb128(&p, pe);
+					printf("  Set File to %ju\n",
+					    (uintmax_t) file);
+					break;
+				case DW_LNS_set_column:
+					column = _decode_uleb128(&p, pe);
+					printf("  Set Column to %ju\n",
+					    (uintmax_t) column);
+					break;
+				case DW_LNS_negate_stmt:
+					is_stmt = !is_stmt;
+					printf("  Set is_stmt to %d\n", is_stmt);
+					break;
+				case DW_LNS_set_basic_block:
+					printf("  Set basic block flag\n");
+					break;
+				case DW_LNS_const_add_pc:
+					address += ADDRESS(255);
+					printf("  Advance PC by constant %ju"
+					    " to %#jx\n",
+					    (uintmax_t) ADDRESS(255),
+					    (uintmax_t) address);
+					break;
+				case DW_LNS_fixed_advance_pc:
+					udelta = re->dw_decode(&p, 2);
+					address += udelta;
+					printf("  Advance PC by fixed value "
+					    "%ju to %#jx\n",
+					    (uintmax_t) udelta,
+					    (uintmax_t) address);
+					break;
+				case DW_LNS_set_prologue_end:
+					printf("  Set prologue end flag\n");
+					break;
+				case DW_LNS_set_epilogue_begin:
+					printf("  Set epilogue begin flag\n");
+					break;
+				case DW_LNS_set_isa:
+					isa = _decode_uleb128(&p, pe);
+					printf("  Set isa to %ju\n",
+					    (uintmax_t) isa);
+					break;
+				default:
+					/* Unrecognized extended opcodes. */
+					printf("  Unknown extended opcode %u\n",
+					    *(p - 1));
+					break;
+				}
+
+			} else {
+				/*
+				 * Special Opcodes.
+				 */
+				line += LINE(*p);
+				address += ADDRESS(*p);
+				printf("  Special opcode %u: advance Address "
+				    "by %ju to %#jx and Line by %jd to %ju\n",
+				    *p - opbase, (uintmax_t) ADDRESS(*p),
+				    (uintmax_t) address, (intmax_t) LINE(*p),
+				    (uintmax_t) line);
+				p++;
+			}
+
+
+		}
+	}
+	if (ret == DW_DLV_ERROR)
+		warnx("dwarf_next_cu_header: %s", dwarf_errmsg(de));
+
+#undef	RESET_REGISTERS
+#undef	LINE
+#undef	ADDRESS
+}
+
+static void
+dump_dwarf_line_decoded(struct readelf *re)
+{
+	Dwarf_Die die;
+	Dwarf_Line *linebuf, ln;
+	Dwarf_Addr lineaddr;
+	Dwarf_Signed linecount, srccount;
+	Dwarf_Unsigned lineno, fn;
+	Dwarf_Error de;
+	const char *dir, *file;
+	char **srcfiles;
+	int i, ret;
+
+	printf("Decoded dump of debug contents of section .debug_line:\n\n");
+	while ((ret = dwarf_next_cu_header(re->dbg, NULL, NULL, NULL, NULL,
+	    NULL, &de)) == DW_DLV_OK) {
+		if (dwarf_siblingof(re->dbg, NULL, &die, &de) != DW_DLV_OK)
+			continue;
+		if (dwarf_attrval_string(die, DW_AT_name, &file, &de) !=
+		    DW_DLV_OK)
+			file = NULL;
+		if (dwarf_attrval_string(die, DW_AT_comp_dir, &dir, &de) !=
+		    DW_DLV_OK)
+			dir = NULL;
+		printf("CU: ");
+		if (dir && file && file[0] != '/')
+			printf("%s/", dir);
+		if (file)
+			printf("%s", file);
+		putchar('\n');
+		printf("%-37s %11s   %s\n", "Filename", "Line Number",
+		    "Starting Address");
+		if (dwarf_srclines(die, &linebuf, &linecount, &de) != DW_DLV_OK)
+			continue;
+		if (dwarf_srcfiles(die, &srcfiles, &srccount, &de) != DW_DLV_OK)
+			continue;
+		for (i = 0; i < linecount; i++) {
+			ln = linebuf[i];
+			if (dwarf_line_srcfileno(ln, &fn, &de) != DW_DLV_OK)
+				continue;
+			if (dwarf_lineno(ln, &lineno, &de) != DW_DLV_OK)
+				continue;
+			if (dwarf_lineaddr(ln, &lineaddr, &de) != DW_DLV_OK)
+				continue;
+			printf("%-37s %11ju %#18jx\n",
+			    basename(srcfiles[fn - 1]), (uintmax_t) lineno,
+			    (uintmax_t) lineaddr);
+		}
+		putchar('\n');
+	}
+}
+
+static void
+dump_dwarf_die(struct readelf *re, Dwarf_Die die, int level)
+{
+	Dwarf_Attribute *attr_list;
+	Dwarf_Die ret_die;
+	Dwarf_Off dieoff, cuoff, culen, attroff;
+	Dwarf_Unsigned ate, lang, v_udata, v_sig;
+	Dwarf_Signed attr_count, v_sdata;
+	Dwarf_Off v_off;
+	Dwarf_Addr v_addr;
+	Dwarf_Half tag, attr, form;
+	Dwarf_Block *v_block;
+	Dwarf_Bool v_bool, is_info;
+	Dwarf_Sig8 v_sig8;
+	Dwarf_Error de;
+	Dwarf_Ptr v_expr;
+	const char *tag_str, *attr_str, *ate_str, *lang_str;
+	char unk_tag[32], unk_attr[32];
+	char *v_str;
+	uint8_t *b, *p;
+	int i, j, abc, ret;
+
+	if (dwarf_dieoffset(die, &dieoff, &de) != DW_DLV_OK) {
+		warnx("dwarf_dieoffset failed: %s", dwarf_errmsg(de));
+		goto cont_search;
+	}
+
+	printf(" <%d><%jx>: ", level, (uintmax_t) dieoff);
+
+	if (dwarf_die_CU_offset_range(die, &cuoff, &culen, &de) != DW_DLV_OK) {
+		warnx("dwarf_die_CU_offset_range failed: %s",
+		      dwarf_errmsg(de));
+		cuoff = 0;
+	}
+
+	abc = dwarf_die_abbrev_code(die);
+	if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
+		warnx("dwarf_tag failed: %s", dwarf_errmsg(de));
+		goto cont_search;
+	}
+	if (dwarf_get_TAG_name(tag, &tag_str) != DW_DLV_OK) {
+		snprintf(unk_tag, sizeof(unk_tag), "[Unknown Tag: %#x]", tag);
+		tag_str = unk_tag;
+	}
+
+	printf("Abbrev Number: %d (%s)\n", abc, tag_str);
+
+	if ((ret = dwarf_attrlist(die, &attr_list, &attr_count, &de)) !=
+	    DW_DLV_OK) {
+		if (ret == DW_DLV_ERROR)
+			warnx("dwarf_attrlist failed: %s", dwarf_errmsg(de));
+		goto cont_search;
+	}
+
+	for (i = 0; i < attr_count; i++) {
+		if (dwarf_whatform(attr_list[i], &form, &de) != DW_DLV_OK) {
+			warnx("dwarf_whatform failed: %s", dwarf_errmsg(de));
+			continue;
+		}
+		if (dwarf_whatattr(attr_list[i], &attr, &de) != DW_DLV_OK) {
+			warnx("dwarf_whatattr failed: %s", dwarf_errmsg(de));
+			continue;
+		}
+		if (dwarf_get_AT_name(attr, &attr_str) != DW_DLV_OK) {
+			snprintf(unk_attr, sizeof(unk_attr),
+			    "[Unknown AT: %#x]", attr);
+			attr_str = unk_attr;
+		}
+		if (dwarf_attroffset(attr_list[i], &attroff, &de) !=
+		    DW_DLV_OK) {
+			warnx("dwarf_attroffset failed: %s", dwarf_errmsg(de));
+			attroff = 0;
+		}
+		printf("    <%jx>   %-18s: ", (uintmax_t) attroff, attr_str);
+		switch (form) {
+		case DW_FORM_ref_addr:
+		case DW_FORM_sec_offset:
+			if (dwarf_global_formref(attr_list[i], &v_off, &de) !=
+			    DW_DLV_OK) {
+				warnx("dwarf_global_formref failed: %s",
+				    dwarf_errmsg(de));
+				continue;
+			}
+			if (form == DW_FORM_ref_addr)
+				printf("<0x%jx>", (uintmax_t) v_off);
+			else
+				printf("0x%jx", (uintmax_t) v_off);
+			break;
+
+		case DW_FORM_ref1:
+		case DW_FORM_ref2:
+		case DW_FORM_ref4:
+		case DW_FORM_ref8:
+		case DW_FORM_ref_udata:
+			if (dwarf_formref(attr_list[i], &v_off, &de) !=
+			    DW_DLV_OK) {
+				warnx("dwarf_formref failed: %s",
+				    dwarf_errmsg(de));
+				continue;
+			}
+			v_off += cuoff;
+			printf("<0x%jx>", (uintmax_t) v_off);
+			break;
+
+		case DW_FORM_addr:
+			if (dwarf_formaddr(attr_list[i], &v_addr, &de) !=
+			    DW_DLV_OK) {
+				warnx("dwarf_formaddr failed: %s",
+				    dwarf_errmsg(de));
+				continue;
+			}
+			printf("%#jx", (uintmax_t) v_addr);
+			break;
+
+		case DW_FORM_data1:
+		case DW_FORM_data2:
+		case DW_FORM_data4:
+		case DW_FORM_data8:
+		case DW_FORM_udata:
+			if (dwarf_formudata(attr_list[i], &v_udata, &de) !=
+			    DW_DLV_OK) {
+				warnx("dwarf_formudata failed: %s",
+				    dwarf_errmsg(de));
+				continue;
+			}
+			if (attr == DW_AT_high_pc)
+				printf("0x%jx", (uintmax_t) v_udata);
+			else
+				printf("%ju", (uintmax_t) v_udata);
+			break;
+
+		case DW_FORM_sdata:
+			if (dwarf_formsdata(attr_list[i], &v_sdata, &de) !=
+			    DW_DLV_OK) {
+				warnx("dwarf_formudata failed: %s",
+				    dwarf_errmsg(de));
+				continue;
+			}
+			printf("%jd", (intmax_t) v_sdata);
+			break;
+
+		case DW_FORM_flag:
+			if (dwarf_formflag(attr_list[i], &v_bool, &de) !=
+			    DW_DLV_OK) {
+				warnx("dwarf_formflag failed: %s",
+				    dwarf_errmsg(de));
+				continue;
+			}
+			printf("%jd", (intmax_t) v_bool);
+			break;
+
+		case DW_FORM_flag_present:
+			putchar('1');
+			break;
+
+		case DW_FORM_string:
+		case DW_FORM_strp:
+			if (dwarf_formstring(attr_list[i], &v_str, &de) !=
+			    DW_DLV_OK) {
+				warnx("dwarf_formstring failed: %s",
+				    dwarf_errmsg(de));
+				continue;
+			}
+			if (form == DW_FORM_string)
+				printf("%s", v_str);
+			else
+				printf("(indirect string) %s", v_str);
+			break;
+
+		case DW_FORM_block:
+		case DW_FORM_block1:
+		case DW_FORM_block2:
+		case DW_FORM_block4:
+			if (dwarf_formblock(attr_list[i], &v_block, &de) !=
+			    DW_DLV_OK) {
+				warnx("dwarf_formblock failed: %s",
+				    dwarf_errmsg(de));
+				continue;
+			}
+			printf("%ju byte block:", (uintmax_t) v_block->bl_len);
+			b = v_block->bl_data;
+			for (j = 0; (Dwarf_Unsigned) j < v_block->bl_len; j++)
+				printf(" %x", b[j]);
+			printf("\t(");
+			dump_dwarf_block(re, v_block->bl_data, v_block->bl_len);
+			putchar(')');
+			break;
+
+		case DW_FORM_exprloc:
+			if (dwarf_formexprloc(attr_list[i], &v_udata, &v_expr,
+			    &de) != DW_DLV_OK) {
+				warnx("dwarf_formexprloc failed: %s",
+				    dwarf_errmsg(de));
+				continue;
+			}
+			printf("%ju byte block:", (uintmax_t) v_udata);
+			b = v_expr;
+			for (j = 0; (Dwarf_Unsigned) j < v_udata; j++)
+				printf(" %x", b[j]);
+			printf("\t(");
+			dump_dwarf_block(re, v_expr, v_udata);
+			putchar(')');
+			break;
+
+		case DW_FORM_ref_sig8:
+			if (dwarf_formsig8(attr_list[i], &v_sig8, &de) !=
+			    DW_DLV_OK) {
+				warnx("dwarf_formsig8 failed: %s",
+				    dwarf_errmsg(de));
+				continue;
+			}
+			p = (uint8_t *)(uintptr_t) &v_sig8.signature[0];
+			v_sig = re->dw_decode(&p, 8);
+			printf("signature: 0x%jx", (uintmax_t) v_sig);
+		}
+		switch (attr) {
+		case DW_AT_encoding:
+			if (dwarf_attrval_unsigned(die, attr, &ate, &de) !=
+			    DW_DLV_OK)
+				break;
+			if (dwarf_get_ATE_name(ate, &ate_str) != DW_DLV_OK)
+				ate_str = "DW_ATE_UNKNOWN";
+			printf("\t(%s)", &ate_str[strlen("DW_ATE_")]);
+			break;
+
+		case DW_AT_language:
+			if (dwarf_attrval_unsigned(die, attr, &lang, &de) !=
+			    DW_DLV_OK)
+				break;
+			if (dwarf_get_LANG_name(lang, &lang_str) != DW_DLV_OK)
+				break;
+			printf("\t(%s)", &lang_str[strlen("DW_LANG_")]);
+			break;
+
+		case DW_AT_location:
+		case DW_AT_string_length:
+		case DW_AT_return_addr:
+		case DW_AT_data_member_location:
+		case DW_AT_frame_base:
+		case DW_AT_segment:
+		case DW_AT_static_link:
+		case DW_AT_use_location:
+		case DW_AT_vtable_elem_location:
+			switch (form) {
+			case DW_FORM_data4:
+			case DW_FORM_data8:
+			case DW_FORM_sec_offset:
+				printf("\t(location list)");
+				break;
+			default:
+				break;
+			}
+
+		default:
+			break;
+		}
+		putchar('\n');
+	}
+
+
+cont_search:
+	/* Search children. */
+	ret = dwarf_child(die, &ret_die, &de);
+	if (ret == DW_DLV_ERROR)
+		warnx("dwarf_child: %s", dwarf_errmsg(de));
+	else if (ret == DW_DLV_OK)
+		dump_dwarf_die(re, ret_die, level + 1);
+
+	/* Search sibling. */
+	is_info = dwarf_get_die_infotypes_flag(die);
+	ret = dwarf_siblingof_b(re->dbg, die, &ret_die, is_info, &de);
+	if (ret == DW_DLV_ERROR)
+		warnx("dwarf_siblingof: %s", dwarf_errmsg(de));
+	else if (ret == DW_DLV_OK)
+		dump_dwarf_die(re, ret_die, level);
+
+	dwarf_dealloc(re->dbg, die, DW_DLA_DIE);
+}
+
+static void
+set_cu_context(struct readelf *re, Dwarf_Half psize, Dwarf_Half osize,
+    Dwarf_Half ver)
+{
+
+	re->cu_psize = psize;
+	re->cu_osize = osize;
+	re->cu_ver = ver;
+}
+
+static void
+dump_dwarf_info(struct readelf *re, Dwarf_Bool is_info)
+{
+	struct section *s;
+	Dwarf_Die die;
+	Dwarf_Error de;
+	Dwarf_Half tag, version, pointer_size, off_size;
+	Dwarf_Off cu_offset, cu_length;
+	Dwarf_Off aboff;
+	Dwarf_Unsigned typeoff;
+	Dwarf_Sig8 sig8;
+	Dwarf_Unsigned sig;
+	uint8_t *p;
+	const char *sn;
+	int i, ret;
+
+	sn = is_info ? ".debug_info" : ".debug_types";
+
+	s = NULL;
+	for (i = 0; (size_t) i < re->shnum; i++) {
+		s = &re->sl[i];
+		if (s->name != NULL && !strcmp(s->name, sn))
+			break;
+	}
+	if ((size_t) i >= re->shnum)
+		return;
+
+	do {
+		printf("\nDump of debug contents of section %s:\n", sn);
+
+		while ((ret = dwarf_next_cu_header_c(re->dbg, is_info, NULL,
+		    &version, &aboff, &pointer_size, &off_size, NULL, &sig8,
+		    &typeoff, NULL, &de)) == DW_DLV_OK) {
+			set_cu_context(re, pointer_size, off_size, version);
+			die = NULL;
+			while (dwarf_siblingof_b(re->dbg, die, &die, is_info,
+			    &de) == DW_DLV_OK) {
+				if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
+					warnx("dwarf_tag failed: %s",
+					    dwarf_errmsg(de));
+					continue;
+				}
+				/* XXX: What about DW_TAG_partial_unit? */
+				if ((is_info && tag == DW_TAG_compile_unit) ||
+				    (!is_info && tag == DW_TAG_type_unit))
+					break;
+			}
+			if (die == NULL && is_info) {
+				warnx("could not find DW_TAG_compile_unit "
+				    "die");
+				continue;
+			} else if (die == NULL && !is_info) {
+				warnx("could not find DW_TAG_type_unit die");
+				continue;
+			}
+
+			if (dwarf_die_CU_offset_range(die, &cu_offset,
+			    &cu_length, &de) != DW_DLV_OK) {
+				warnx("dwarf_die_CU_offset failed: %s",
+				    dwarf_errmsg(de));
+				continue;
+			}
+
+			cu_length -= off_size == 4 ? 4 : 12;
+
+			sig = 0;
+			if (!is_info) {
+				p = (uint8_t *)(uintptr_t) &sig8.signature[0];
+				sig = re->dw_decode(&p, 8);
+			}
+
+			printf("\n  Type Unit @ offset 0x%jx:\n",
+			    (uintmax_t) cu_offset);
+			printf("    Length:\t\t%#jx (%d-bit)\n",
+			    (uintmax_t) cu_length, off_size == 4 ? 32 : 64);
+			printf("    Version:\t\t%u\n", version);
+			printf("    Abbrev Offset:\t0x%jx\n",
+			    (uintmax_t) aboff);
+			printf("    Pointer Size:\t%u\n", pointer_size);
+			if (!is_info) {
+				printf("    Signature:\t\t0x%016jx\n",
+				    (uintmax_t) sig);
+				printf("    Type Offset:\t0x%jx\n",
+				    (uintmax_t) typeoff);
+			}
+
+			dump_dwarf_die(re, die, 0);
+		}
+		if (ret == DW_DLV_ERROR)
+			warnx("dwarf_next_cu_header: %s", dwarf_errmsg(de));
+		if (is_info)
+			break;
+	} while (dwarf_next_types_section(re->dbg, &de) == DW_DLV_OK);
+}
+
+static void
+dump_dwarf_abbrev(struct readelf *re)
+{
+	Dwarf_Abbrev ab;
+	Dwarf_Off aboff, atoff;
+	Dwarf_Unsigned length, attr_count;
+	Dwarf_Signed flag, form;
+	Dwarf_Half tag, attr;
+	Dwarf_Error de;
+	const char *tag_str, *attr_str, *form_str;
+	char unk_tag[32], unk_attr[32], unk_form[32];
+	int i, j, ret;
+
+	printf("\nContents of section .debug_abbrev:\n\n");
+
+	while ((ret = dwarf_next_cu_header(re->dbg, NULL, NULL, &aboff,
+	    NULL, NULL, &de)) ==  DW_DLV_OK) {
+		printf("  Number TAG\n");
+		i = 0;
+		while ((ret = dwarf_get_abbrev(re->dbg, aboff, &ab, &length,
+		    &attr_count, &de)) == DW_DLV_OK) {
+			if (length == 1) {
+				dwarf_dealloc(re->dbg, ab, DW_DLA_ABBREV);
+				break;
+			}
+			aboff += length;
+			printf("%4d", ++i);
+			if (dwarf_get_abbrev_tag(ab, &tag, &de) != DW_DLV_OK) {
+				warnx("dwarf_get_abbrev_tag failed: %s",
+				    dwarf_errmsg(de));
+				goto next_abbrev;
+			}
+			if (dwarf_get_TAG_name(tag, &tag_str) != DW_DLV_OK) {
+				snprintf(unk_tag, sizeof(unk_tag),
+				    "[Unknown Tag: %#x]", tag);
+				tag_str = unk_tag;
+			}
+			if (dwarf_get_abbrev_children_flag(ab, &flag, &de) !=
+			    DW_DLV_OK) {
+				warnx("dwarf_get_abbrev_children_flag failed:"
+				    " %s", dwarf_errmsg(de));
+				goto next_abbrev;
+			}
+			printf("      %s    %s\n", tag_str,
+			    flag ? "[has children]" : "[no children]");
+			for (j = 0; (Dwarf_Unsigned) j < attr_count; j++) {
+				if (dwarf_get_abbrev_entry(ab, (Dwarf_Signed) j,
+				    &attr, &form, &atoff, &de) != DW_DLV_OK) {
+					warnx("dwarf_get_abbrev_entry failed:"
+					    " %s", dwarf_errmsg(de));
+					continue;
+				}
+				if (dwarf_get_AT_name(attr, &attr_str) !=
+				    DW_DLV_OK) {
+					snprintf(unk_attr, sizeof(unk_attr),
+					    "[Unknown AT: %#x]", attr);
+					attr_str = unk_attr;
+				}
+				if (dwarf_get_FORM_name(form, &form_str) !=
+				    DW_DLV_OK) {
+					snprintf(unk_form, sizeof(unk_form),
+					    "[Unknown Form: %#x]",
+					    (Dwarf_Half) form);
+					form_str = unk_form;
+				}
+				printf("    %-18s %s\n", attr_str, form_str);
+			}
+		next_abbrev:
+			dwarf_dealloc(re->dbg, ab, DW_DLA_ABBREV);
+		}
+		if (ret != DW_DLV_OK)
+			warnx("dwarf_get_abbrev: %s", dwarf_errmsg(de));
+	}
+	if (ret == DW_DLV_ERROR)
+		warnx("dwarf_next_cu_header: %s", dwarf_errmsg(de));
+}
+
+static void
+dump_dwarf_pubnames(struct readelf *re)
+{
+	struct section *s;
+	Dwarf_Off die_off;
+	Dwarf_Unsigned offset, length, nt_cu_offset, nt_cu_length;
+	Dwarf_Signed cnt;
+	Dwarf_Global *globs;
+	Dwarf_Half nt_version;
+	Dwarf_Error de;
+	Elf_Data *d;
+	char *glob_name;
+	int i, dwarf_size, elferr;
+
+	printf("\nContents of the .debug_pubnames section:\n");
+
+	s = NULL;
+	for (i = 0; (size_t) i < re->shnum; i++) {
+		s = &re->sl[i];
+		if (s->name != NULL && !strcmp(s->name, ".debug_pubnames"))
+			break;
+	}
+	if ((size_t) i >= re->shnum)
+		return;
+
+	(void) elf_errno();
+	if ((d = elf_getdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_getdata failed: %s", elf_errmsg(-1));
+		return;
+	}
+	if (d->d_size <= 0)
+		return;
+
+	/* Read in .debug_pubnames section table header. */
+	offset = 0;
+	length = re->dw_read(d, &offset, 4);
+	if (length == 0xffffffff) {
+		dwarf_size = 8;
+		length = re->dw_read(d, &offset, 8);
+	} else
+		dwarf_size = 4;
+
+	if (length > d->d_size - offset) {
+		warnx("invalid .dwarf_pubnames section");
+		return;
+	}
+
+	nt_version = re->dw_read(d, &offset, 2);
+	nt_cu_offset = re->dw_read(d, &offset, dwarf_size);
+	nt_cu_length = re->dw_read(d, &offset, dwarf_size);
+	printf("  Length:\t\t\t\t%ju\n", (uintmax_t) length);
+	printf("  Version:\t\t\t\t%u\n", nt_version);
+	printf("  Offset into .debug_info section:\t%ju\n",
+	    (uintmax_t) nt_cu_offset);
+	printf("  Size of area in .debug_info section:\t%ju\n",
+	    (uintmax_t) nt_cu_length);
+
+	if (dwarf_get_globals(re->dbg, &globs, &cnt, &de) != DW_DLV_OK) {
+		warnx("dwarf_get_globals failed: %s", dwarf_errmsg(de));
+		return;
+	}
+
+	printf("\n    Offset      Name\n");
+	for (i = 0; i < cnt; i++) {
+		if (dwarf_globname(globs[i], &glob_name, &de) != DW_DLV_OK) {
+			warnx("dwarf_globname failed: %s", dwarf_errmsg(de));
+			continue;
+		}
+		if (dwarf_global_die_offset(globs[i], &die_off, &de) !=
+		    DW_DLV_OK) {
+			warnx("dwarf_global_die_offset failed: %s",
+			    dwarf_errmsg(de));
+			continue;
+		}
+		printf("    %-11ju %s\n", (uintmax_t) die_off, glob_name);
+	}
+}
+
+static void
+dump_dwarf_aranges(struct readelf *re)
+{
+	struct section *s;
+	Dwarf_Arange *aranges;
+	Dwarf_Addr start;
+	Dwarf_Unsigned offset, length, as_cu_offset;
+	Dwarf_Off die_off;
+	Dwarf_Signed cnt;
+	Dwarf_Half as_version, as_addrsz, as_segsz;
+	Dwarf_Error de;
+	Elf_Data *d;
+	int i, dwarf_size, elferr;
+
+	printf("\nContents of section .debug_aranges:\n");
+
+	s = NULL;
+	for (i = 0; (size_t) i < re->shnum; i++) {
+		s = &re->sl[i];
+		if (s->name != NULL && !strcmp(s->name, ".debug_aranges"))
+			break;
+	}
+	if ((size_t) i >= re->shnum)
+		return;
+
+	(void) elf_errno();
+	if ((d = elf_getdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_getdata failed: %s", elf_errmsg(-1));
+		return;
+	}
+	if (d->d_size <= 0)
+		return;
+
+	/* Read in the .debug_aranges section table header. */
+	offset = 0;
+	length = re->dw_read(d, &offset, 4);
+	if (length == 0xffffffff) {
+		dwarf_size = 8;
+		length = re->dw_read(d, &offset, 8);
+	} else
+		dwarf_size = 4;
+
+	if (length > d->d_size - offset) {
+		warnx("invalid .dwarf_aranges section");
+		return;
+	}
+
+	as_version = re->dw_read(d, &offset, 2);
+	as_cu_offset = re->dw_read(d, &offset, dwarf_size);
+	as_addrsz = re->dw_read(d, &offset, 1);
+	as_segsz = re->dw_read(d, &offset, 1);
+
+	printf("  Length:\t\t\t%ju\n", (uintmax_t) length);
+	printf("  Version:\t\t\t%u\n", as_version);
+	printf("  Offset into .debug_info:\t%ju\n", (uintmax_t) as_cu_offset);
+	printf("  Pointer Size:\t\t\t%u\n", as_addrsz);
+	printf("  Segment Size:\t\t\t%u\n", as_segsz);
+
+	if (dwarf_get_aranges(re->dbg, &aranges, &cnt, &de) != DW_DLV_OK) {
+		warnx("dwarf_get_aranges failed: %s", dwarf_errmsg(de));
+		return;
+	}
+
+	printf("\n    Address  Length\n");
+	for (i = 0; i < cnt; i++) {
+		if (dwarf_get_arange_info(aranges[i], &start, &length,
+		    &die_off, &de) != DW_DLV_OK) {
+			warnx("dwarf_get_arange_info failed: %s",
+			    dwarf_errmsg(de));
+			continue;
+		}
+		printf("    %08jx %ju\n", (uintmax_t) start,
+		    (uintmax_t) length);
+	}
+}
+
+static void
+dump_dwarf_ranges_foreach(struct readelf *re, Dwarf_Die die, Dwarf_Addr base)
+{
+	Dwarf_Attribute *attr_list;
+	Dwarf_Ranges *ranges;
+	Dwarf_Die ret_die;
+	Dwarf_Error de;
+	Dwarf_Addr base0;
+	Dwarf_Half attr;
+	Dwarf_Signed attr_count, cnt;
+	Dwarf_Unsigned off, bytecnt;
+	int i, j, ret;
+
+	if ((ret = dwarf_attrlist(die, &attr_list, &attr_count, &de)) !=
+	    DW_DLV_OK) {
+		if (ret == DW_DLV_ERROR)
+			warnx("dwarf_attrlist failed: %s", dwarf_errmsg(de));
+		goto cont_search;
+	}
+
+	for (i = 0; i < attr_count; i++) {
+		if (dwarf_whatattr(attr_list[i], &attr, &de) != DW_DLV_OK) {
+			warnx("dwarf_whatattr failed: %s", dwarf_errmsg(de));
+			continue;
+		}
+		if (attr != DW_AT_ranges)
+			continue;
+		if (dwarf_formudata(attr_list[i], &off, &de) != DW_DLV_OK) {
+			warnx("dwarf_formudata failed: %s", dwarf_errmsg(de));
+			continue;
+		}
+		if (dwarf_get_ranges(re->dbg, (Dwarf_Off) off, &ranges, &cnt,
+		    &bytecnt, &de) != DW_DLV_OK)
+			continue;
+		base0 = base;
+		for (j = 0; j < cnt; j++) {
+			printf("    %08jx ", (uintmax_t) off);
+			if (ranges[j].dwr_type == DW_RANGES_END) {
+				printf("%s\n", "<End of list>");
+				continue;
+			} else if (ranges[j].dwr_type ==
+			    DW_RANGES_ADDRESS_SELECTION) {
+				base0 = ranges[j].dwr_addr2;
+				continue;
+			}
+			if (re->ec == ELFCLASS32)
+				printf("%08jx %08jx\n",
+				    (uintmax_t) (ranges[j].dwr_addr1 + base0),
+				    (uintmax_t) (ranges[j].dwr_addr2 + base0));
+			else
+				printf("%016jx %016jx\n",
+				    (uintmax_t) (ranges[j].dwr_addr1 + base0),
+				    (uintmax_t) (ranges[j].dwr_addr2 + base0));
+		}
+	}
+
+cont_search:
+	/* Search children. */
+	ret = dwarf_child(die, &ret_die, &de);
+	if (ret == DW_DLV_ERROR)
+		warnx("dwarf_child: %s", dwarf_errmsg(de));
+	else if (ret == DW_DLV_OK)
+		dump_dwarf_ranges_foreach(re, ret_die, base);
+
+	/* Search sibling. */
+	ret = dwarf_siblingof(re->dbg, die, &ret_die, &de);
+	if (ret == DW_DLV_ERROR)
+		warnx("dwarf_siblingof: %s", dwarf_errmsg(de));
+	else if (ret == DW_DLV_OK)
+		dump_dwarf_ranges_foreach(re, ret_die, base);
+}
+
+static void
+dump_dwarf_ranges(struct readelf *re)
+{
+	Dwarf_Ranges *ranges;
+	Dwarf_Die die;
+	Dwarf_Signed cnt;
+	Dwarf_Unsigned bytecnt;
+	Dwarf_Half tag;
+	Dwarf_Error de;
+	Dwarf_Unsigned lowpc;
+	int ret;
+
+	if (dwarf_get_ranges(re->dbg, 0, &ranges, &cnt, &bytecnt, &de) !=
+	    DW_DLV_OK)
+		return;
+
+	printf("Contents of the .debug_ranges section:\n\n");
+	if (re->ec == ELFCLASS32)
+		printf("    %-8s %-8s %s\n", "Offset", "Begin", "End");
+	else
+		printf("    %-8s %-16s %s\n", "Offset", "Begin", "End");
+
+	while ((ret = dwarf_next_cu_header(re->dbg, NULL, NULL, NULL, NULL,
+	    NULL, &de)) == DW_DLV_OK) {
+		die = NULL;
+		if (dwarf_siblingof(re->dbg, die, &die, &de) != DW_DLV_OK)
+			continue;
+		if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
+			warnx("dwarf_tag failed: %s", dwarf_errmsg(de));
+			continue;
+		}
+		/* XXX: What about DW_TAG_partial_unit? */
+		lowpc = 0;
+		if (tag == DW_TAG_compile_unit) {
+			if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lowpc,
+			    &de) != DW_DLV_OK)
+				lowpc = 0;
+		}
+
+		dump_dwarf_ranges_foreach(re, die, (Dwarf_Addr) lowpc);
+	}
+	putchar('\n');
+}
+
+static void
+dump_dwarf_macinfo(struct readelf *re)
+{
+	Dwarf_Unsigned offset;
+	Dwarf_Signed cnt;
+	Dwarf_Macro_Details *md;
+	Dwarf_Error de;
+	const char *mi_str;
+	char unk_mi[32];
+	int i;
+
+#define	_MAX_MACINFO_ENTRY	65535
+
+	printf("\nContents of section .debug_macinfo:\n\n");
+
+	offset = 0;
+	while (dwarf_get_macro_details(re->dbg, offset, _MAX_MACINFO_ENTRY,
+	    &cnt, &md, &de) == DW_DLV_OK) {
+		for (i = 0; i < cnt; i++) {
+			offset = md[i].dmd_offset + 1;
+			if (md[i].dmd_type == 0)
+				break;
+			if (dwarf_get_MACINFO_name(md[i].dmd_type, &mi_str) !=
+			    DW_DLV_OK) {
+				snprintf(unk_mi, sizeof(unk_mi),
+				    "[Unknown MACINFO: %#x]", md[i].dmd_type);
+				mi_str = unk_mi;
+			}
+			printf(" %s", mi_str);
+			switch (md[i].dmd_type) {
+			case DW_MACINFO_define:
+			case DW_MACINFO_undef:
+				printf(" - lineno : %jd macro : %s\n",
+				    (intmax_t) md[i].dmd_lineno,
+				    md[i].dmd_macro);
+				break;
+			case DW_MACINFO_start_file:
+				printf(" - lineno : %jd filenum : %jd\n",
+				    (intmax_t) md[i].dmd_lineno,
+				    (intmax_t) md[i].dmd_fileindex);
+				break;
+			default:
+				putchar('\n');
+				break;
+			}
+		}
+	}
+
+#undef	_MAX_MACINFO_ENTRY
+}
+
+static void
+dump_dwarf_frame_inst(struct readelf *re, Dwarf_Cie cie, uint8_t *insts,
+    Dwarf_Unsigned len, Dwarf_Unsigned caf, Dwarf_Signed daf, Dwarf_Addr pc,
+    Dwarf_Debug dbg)
+{
+	Dwarf_Frame_Op *oplist;
+	Dwarf_Signed opcnt, delta;
+	Dwarf_Small op;
+	Dwarf_Error de;
+	const char *op_str;
+	char unk_op[32];
+	int i;
+
+	if (dwarf_expand_frame_instructions(cie, insts, len, &oplist,
+	    &opcnt, &de) != DW_DLV_OK) {
+		warnx("dwarf_expand_frame_instructions failed: %s",
+		    dwarf_errmsg(de));
+		return;
+	}
+
+	for (i = 0; i < opcnt; i++) {
+		if (oplist[i].fp_base_op != 0)
+			op = oplist[i].fp_base_op << 6;
+		else
+			op = oplist[i].fp_extended_op;
+		if (dwarf_get_CFA_name(op, &op_str) != DW_DLV_OK) {
+			snprintf(unk_op, sizeof(unk_op), "[Unknown CFA: %#x]",
+			    op);
+			op_str = unk_op;
+		}
+		printf("  %s", op_str);
+		switch (op) {
+		case DW_CFA_advance_loc:
+			delta = oplist[i].fp_offset * caf;
+			pc += delta;
+			printf(": %ju to %08jx", (uintmax_t) delta,
+			    (uintmax_t) pc);
+			break;
+		case DW_CFA_offset:
+		case DW_CFA_offset_extended:
+		case DW_CFA_offset_extended_sf:
+			delta = oplist[i].fp_offset * daf;
+			printf(": r%u (%s) at cfa%+jd", oplist[i].fp_register,
+			    dwarf_regname(re, oplist[i].fp_register),
+			    (intmax_t) delta);
+			break;
+		case DW_CFA_restore:
+			printf(": r%u (%s)", oplist[i].fp_register,
+			    dwarf_regname(re, oplist[i].fp_register));
+			break;
+		case DW_CFA_set_loc:
+			pc = oplist[i].fp_offset;
+			printf(": to %08jx", (uintmax_t) pc);
+			break;
+		case DW_CFA_advance_loc1:
+		case DW_CFA_advance_loc2:
+		case DW_CFA_advance_loc4:
+			pc += oplist[i].fp_offset;
+			printf(": %jd to %08jx", (intmax_t) oplist[i].fp_offset,
+			    (uintmax_t) pc);
+			break;
+		case DW_CFA_def_cfa:
+			printf(": r%u (%s) ofs %ju", oplist[i].fp_register,
+			    dwarf_regname(re, oplist[i].fp_register),
+			    (uintmax_t) oplist[i].fp_offset);
+			break;
+		case DW_CFA_def_cfa_sf:
+			printf(": r%u (%s) ofs %jd", oplist[i].fp_register,
+			    dwarf_regname(re, oplist[i].fp_register),
+			    (intmax_t) (oplist[i].fp_offset * daf));
+			break;
+		case DW_CFA_def_cfa_register:
+			printf(": r%u (%s)", oplist[i].fp_register,
+			    dwarf_regname(re, oplist[i].fp_register));
+			break;
+		case DW_CFA_def_cfa_offset:
+			printf(": %ju", (uintmax_t) oplist[i].fp_offset);
+			break;
+		case DW_CFA_def_cfa_offset_sf:
+			printf(": %jd", (intmax_t) (oplist[i].fp_offset * daf));
+			break;
+		default:
+			break;
+		}
+		putchar('\n');
+	}
+
+	dwarf_dealloc(dbg, oplist, DW_DLA_FRAME_BLOCK);
+}
+
+static char *
+get_regoff_str(struct readelf *re, Dwarf_Half reg, Dwarf_Addr off)
+{
+	static char rs[16];
+
+	if (reg == DW_FRAME_UNDEFINED_VAL || reg == DW_FRAME_REG_INITIAL_VALUE)
+		snprintf(rs, sizeof(rs), "%c", 'u');
+	else if (reg == DW_FRAME_CFA_COL)
+		snprintf(rs, sizeof(rs), "c%+jd", (intmax_t) off);
+	else
+		snprintf(rs, sizeof(rs), "%s%+jd", dwarf_regname(re, reg),
+		    (intmax_t) off);
+
+	return (rs);
+}
+
+static int
+dump_dwarf_frame_regtable(struct readelf *re, Dwarf_Fde fde, Dwarf_Addr pc,
+    Dwarf_Unsigned func_len, Dwarf_Half cie_ra)
+{
+	Dwarf_Regtable rt;
+	Dwarf_Addr row_pc, end_pc, pre_pc, cur_pc;
+	Dwarf_Error de;
+	char *vec;
+	int i;
+
+#define BIT_SET(v, n) (v[(n)>>3] |= 1U << ((n) & 7))
+#define BIT_CLR(v, n) (v[(n)>>3] &= ~(1U << ((n) & 7)))
+#define BIT_ISSET(v, n) (v[(n)>>3] & (1U << ((n) & 7)))
+#define	RT(x) rt.rules[(x)]
+
+	vec = calloc((DW_REG_TABLE_SIZE + 7) / 8, 1);
+	if (vec == NULL)
+		err(EXIT_FAILURE, "calloc failed");
+
+	pre_pc = ~((Dwarf_Addr) 0);
+	cur_pc = pc;
+	end_pc = pc + func_len;
+	for (; cur_pc < end_pc; cur_pc++) {
+		if (dwarf_get_fde_info_for_all_regs(fde, cur_pc, &rt, &row_pc,
+		    &de) != DW_DLV_OK) {
+			warnx("dwarf_get_fde_info_for_all_regs failed: %s\n",
+			    dwarf_errmsg(de));
+			return (-1);
+		}
+		if (row_pc == pre_pc)
+			continue;
+		pre_pc = row_pc;
+		for (i = 1; i < DW_REG_TABLE_SIZE; i++) {
+			if (rt.rules[i].dw_regnum != DW_FRAME_REG_INITIAL_VALUE)
+				BIT_SET(vec, i);
+		}
+	}
+
+	printf("   LOC   CFA      ");
+	for (i = 1; i < DW_REG_TABLE_SIZE; i++) {
+		if (BIT_ISSET(vec, i)) {
+			if ((Dwarf_Half) i == cie_ra)
+				printf("ra   ");
+			else
+				printf("%-5s",
+				    dwarf_regname(re, (unsigned int) i));
+		}
+	}
+	putchar('\n');
+
+	pre_pc = ~((Dwarf_Addr) 0);
+	cur_pc = pc;
+	end_pc = pc + func_len;
+	for (; cur_pc < end_pc; cur_pc++) {
+		if (dwarf_get_fde_info_for_all_regs(fde, cur_pc, &rt, &row_pc,
+		    &de) != DW_DLV_OK) {
+			warnx("dwarf_get_fde_info_for_all_regs failed: %s\n",
+			    dwarf_errmsg(de));
+			return (-1);
+		}
+		if (row_pc == pre_pc)
+			continue;
+		pre_pc = row_pc;
+		printf("%08jx ", (uintmax_t) row_pc);
+		printf("%-8s ", get_regoff_str(re, RT(0).dw_regnum,
+		    RT(0).dw_offset));
+		for (i = 1; i < DW_REG_TABLE_SIZE; i++) {
+			if (BIT_ISSET(vec, i)) {
+				printf("%-5s", get_regoff_str(re,
+				    RT(i).dw_regnum, RT(i).dw_offset));
+			}
+		}
+		putchar('\n');
+	}
+
+	free(vec);
+
+	return (0);
+
+#undef	BIT_SET
+#undef	BIT_CLR
+#undef	BIT_ISSET
+#undef	RT
+}
+
+static void
+dump_dwarf_frame_section(struct readelf *re, struct section *s, int alt)
+{
+	Dwarf_Cie *cie_list, cie, pre_cie;
+	Dwarf_Fde *fde_list, fde;
+	Dwarf_Off cie_offset, fde_offset;
+	Dwarf_Unsigned cie_length, fde_instlen;
+	Dwarf_Unsigned cie_caf, cie_daf, cie_instlen, func_len, fde_length;
+	Dwarf_Signed cie_count, fde_count, cie_index;
+	Dwarf_Addr low_pc;
+	Dwarf_Half cie_ra;
+	Dwarf_Small cie_version;
+	Dwarf_Ptr fde_addr, fde_inst, cie_inst;
+	char *cie_aug, c;
+	int i, eh_frame;
+	Dwarf_Error de;
+
+	printf("\nThe section %s contains:\n\n", s->name);
+
+	if (!strcmp(s->name, ".debug_frame")) {
+		eh_frame = 0;
+		if (dwarf_get_fde_list(re->dbg, &cie_list, &cie_count,
+		    &fde_list, &fde_count, &de) != DW_DLV_OK) {
+			warnx("dwarf_get_fde_list failed: %s",
+			    dwarf_errmsg(de));
+			return;
+		}
+	} else if (!strcmp(s->name, ".eh_frame")) {
+		eh_frame = 1;
+		if (dwarf_get_fde_list_eh(re->dbg, &cie_list, &cie_count,
+		    &fde_list, &fde_count, &de) != DW_DLV_OK) {
+			warnx("dwarf_get_fde_list_eh failed: %s",
+			    dwarf_errmsg(de));
+			return;
+		}
+	} else
+		return;
+
+	pre_cie = NULL;
+	for (i = 0; i < fde_count; i++) {
+		if (dwarf_get_fde_n(fde_list, i, &fde, &de) != DW_DLV_OK) {
+			warnx("dwarf_get_fde_n failed: %s", dwarf_errmsg(de));
+			continue;
+		}
+		if (dwarf_get_cie_of_fde(fde, &cie, &de) != DW_DLV_OK) {
+			warnx("dwarf_get_fde_n failed: %s", dwarf_errmsg(de));
+			continue;
+		}
+		if (dwarf_get_fde_range(fde, &low_pc, &func_len, &fde_addr,
+		    &fde_length, &cie_offset, &cie_index, &fde_offset,
+		    &de) != DW_DLV_OK) {
+			warnx("dwarf_get_fde_range failed: %s",
+			    dwarf_errmsg(de));
+			continue;
+		}
+		if (dwarf_get_fde_instr_bytes(fde, &fde_inst, &fde_instlen,
+		    &de) != DW_DLV_OK) {
+			warnx("dwarf_get_fde_instr_bytes failed: %s",
+			    dwarf_errmsg(de));
+			continue;
+		}
+		if (pre_cie == NULL || cie != pre_cie) {
+			pre_cie = cie;
+			if (dwarf_get_cie_info(cie, &cie_length, &cie_version,
+			    &cie_aug, &cie_caf, &cie_daf, &cie_ra,
+			    &cie_inst, &cie_instlen, &de) != DW_DLV_OK) {
+				warnx("dwarf_get_cie_info failed: %s",
+				    dwarf_errmsg(de));
+				continue;
+			}
+			printf("%08jx %08jx %8.8jx CIE",
+			    (uintmax_t) cie_offset,
+			    (uintmax_t) cie_length,
+			    (uintmax_t) (eh_frame ? 0 : ~0U));
+			if (!alt) {
+				putchar('\n');
+				printf("  Version:\t\t\t%u\n", cie_version);
+				printf("  Augmentation:\t\t\t\"");
+				while ((c = *cie_aug++) != '\0')
+					putchar(c);
+				printf("\"\n");
+				printf("  Code alignment factor:\t%ju\n",
+				    (uintmax_t) cie_caf);
+				printf("  Data alignment factor:\t%jd\n",
+				    (intmax_t) cie_daf);
+				printf("  Return address column:\t%ju\n",
+				    (uintmax_t) cie_ra);
+				putchar('\n');
+				dump_dwarf_frame_inst(re, cie, cie_inst,
+				    cie_instlen, cie_caf, cie_daf, 0,
+				    re->dbg);
+				putchar('\n');
+			} else {
+				printf(" \"");
+				while ((c = *cie_aug++) != '\0')
+					putchar(c);
+				putchar('"');
+				printf(" cf=%ju df=%jd ra=%ju\n",
+				    (uintmax_t) cie_caf,
+				    (uintmax_t) cie_daf,
+				    (uintmax_t) cie_ra);
+				dump_dwarf_frame_regtable(re, fde, low_pc, 1,
+				    cie_ra);
+				putchar('\n');
+			}
+		}
+		printf("%08jx %08jx %08jx FDE cie=%08jx pc=%08jx..%08jx\n",
+		    (uintmax_t) fde_offset, (uintmax_t) fde_length,
+		    (uintmax_t) cie_offset,
+		    (uintmax_t) (eh_frame ? fde_offset + 4 - cie_offset :
+			cie_offset),
+		    (uintmax_t) low_pc, (uintmax_t) (low_pc + func_len));
+		if (!alt)
+			dump_dwarf_frame_inst(re, cie, fde_inst, fde_instlen,
+			    cie_caf, cie_daf, low_pc, re->dbg);
+		else
+			dump_dwarf_frame_regtable(re, fde, low_pc, func_len,
+			    cie_ra);
+		putchar('\n');
+	}
+}
+
+static void
+dump_dwarf_frame(struct readelf *re, int alt)
+{
+	struct section *s;
+	int i;
+
+	(void) dwarf_set_frame_cfa_value(re->dbg, DW_FRAME_CFA_COL);
+
+	for (i = 0; (size_t) i < re->shnum; i++) {
+		s = &re->sl[i];
+		if (s->name != NULL && (!strcmp(s->name, ".debug_frame") ||
+		    !strcmp(s->name, ".eh_frame")))
+			dump_dwarf_frame_section(re, s, alt);
+	}
+}
+
+static void
+dump_dwarf_str(struct readelf *re)
+{
+	struct section *s;
+	Elf_Data *d;
+	unsigned char *p;
+	int elferr, end, i, j;
+
+	printf("\nContents of section .debug_str:\n");
+
+	s = NULL;
+	for (i = 0; (size_t) i < re->shnum; i++) {
+		s = &re->sl[i];
+		if (s->name != NULL && !strcmp(s->name, ".debug_str"))
+			break;
+	}
+	if ((size_t) i >= re->shnum)
+		return;
+
+	(void) elf_errno();
+	if ((d = elf_getdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_getdata failed: %s", elf_errmsg(-1));
+		return;
+	}
+	if (d->d_size <= 0)
+		return;
+
+	for (i = 0, p = d->d_buf; (size_t) i < d->d_size; i += 16) {
+		printf("  0x%08x", (unsigned int) i);
+		if ((size_t) i + 16 > d->d_size)
+			end = d->d_size;
+		else
+			end = i + 16;
+		for (j = i; j < i + 16; j++) {
+			if ((j - i) % 4 == 0)
+				putchar(' ');
+			if (j >= end) {
+				printf("  ");
+				continue;
+			}
+			printf("%02x", (uint8_t) p[j]);
+		}
+		putchar(' ');
+		for (j = i; j < end; j++) {
+			if (isprint(p[j]))
+				putchar(p[j]);
+			else if (p[j] == 0)
+				putchar('.');
+			else
+				putchar(' ');
+		}
+		putchar('\n');
+	}
+}
+
+struct loc_at {
+	Dwarf_Attribute la_at;
+	Dwarf_Unsigned la_off;
+	Dwarf_Unsigned la_lowpc;
+	Dwarf_Half la_cu_psize;
+	Dwarf_Half la_cu_osize;
+	Dwarf_Half la_cu_ver;
+	TAILQ_ENTRY(loc_at) la_next;
+};
+
+static TAILQ_HEAD(, loc_at) lalist = TAILQ_HEAD_INITIALIZER(lalist);
+
+static void
+search_loclist_at(struct readelf *re, Dwarf_Die die, Dwarf_Unsigned lowpc)
+{
+	Dwarf_Attribute *attr_list;
+	Dwarf_Die ret_die;
+	Dwarf_Unsigned off;
+	Dwarf_Off ref;
+	Dwarf_Signed attr_count;
+	Dwarf_Half attr, form;
+	Dwarf_Bool is_info;
+	Dwarf_Error de;
+	struct loc_at *la, *nla;
+	int i, ret;
+
+	is_info = dwarf_get_die_infotypes_flag(die);
+
+	if ((ret = dwarf_attrlist(die, &attr_list, &attr_count, &de)) !=
+	    DW_DLV_OK) {
+		if (ret == DW_DLV_ERROR)
+			warnx("dwarf_attrlist failed: %s", dwarf_errmsg(de));
+		goto cont_search;
+	}
+	for (i = 0; i < attr_count; i++) {
+		if (dwarf_whatattr(attr_list[i], &attr, &de) != DW_DLV_OK) {
+			warnx("dwarf_whatattr failed: %s", dwarf_errmsg(de));
+			continue;
+		}
+		if (attr != DW_AT_location &&
+		    attr != DW_AT_string_length &&
+		    attr != DW_AT_return_addr &&
+		    attr != DW_AT_data_member_location &&
+		    attr != DW_AT_frame_base &&
+		    attr != DW_AT_segment &&
+		    attr != DW_AT_static_link &&
+		    attr != DW_AT_use_location &&
+		    attr != DW_AT_vtable_elem_location)
+			continue;
+		if (dwarf_whatform(attr_list[i], &form, &de) != DW_DLV_OK) {
+			warnx("dwarf_whatform failed: %s", dwarf_errmsg(de));
+			continue;
+		}
+		if (form == DW_FORM_data4 || form == DW_FORM_data8) {
+			if (dwarf_formudata(attr_list[i], &off, &de) !=
+			    DW_DLV_OK) {
+				warnx("dwarf_formudata failed: %s",
+				    dwarf_errmsg(de));
+				continue;
+			}
+		} else if (form == DW_FORM_sec_offset) {
+			if (dwarf_global_formref(attr_list[i], &ref, &de) !=
+			    DW_DLV_OK) {
+				warnx("dwarf_global_formref failed: %s",
+				    dwarf_errmsg(de));
+				continue;
+			}
+			off = ref;
+		} else
+			continue;
+
+		TAILQ_FOREACH(la, &lalist, la_next) {
+			if (off == la->la_off)
+				break;
+			if (off < la->la_off) {
+				if ((nla = malloc(sizeof(*nla))) == NULL)
+					err(EXIT_FAILURE, "malloc failed");
+				nla->la_at = attr_list[i];
+				nla->la_off = off;
+				nla->la_lowpc = lowpc;
+				nla->la_cu_psize = re->cu_psize;
+				nla->la_cu_osize = re->cu_osize;
+				nla->la_cu_ver = re->cu_ver;
+				TAILQ_INSERT_BEFORE(la, nla, la_next);
+				break;
+			}
+		}
+		if (la == NULL) {
+			if ((nla = malloc(sizeof(*nla))) == NULL)
+				err(EXIT_FAILURE, "malloc failed");
+			nla->la_at = attr_list[i];
+			nla->la_off = off;
+			nla->la_lowpc = lowpc;
+			nla->la_cu_psize = re->cu_psize;
+			nla->la_cu_osize = re->cu_osize;
+			nla->la_cu_ver = re->cu_ver;
+			TAILQ_INSERT_TAIL(&lalist, nla, la_next);
+		}
+	}
+
+cont_search:
+	/* Search children. */
+	ret = dwarf_child(die, &ret_die, &de);
+	if (ret == DW_DLV_ERROR)
+		warnx("dwarf_child: %s", dwarf_errmsg(de));
+	else if (ret == DW_DLV_OK)
+		search_loclist_at(re, ret_die, lowpc);
+
+	/* Search sibling. */
+	ret = dwarf_siblingof_b(re->dbg, die, &ret_die, is_info, &de);
+	if (ret == DW_DLV_ERROR)
+		warnx("dwarf_siblingof: %s", dwarf_errmsg(de));
+	else if (ret == DW_DLV_OK)
+		search_loclist_at(re, ret_die, lowpc);
+}
+
+static void
+dump_dwarf_loc(struct readelf *re, Dwarf_Loc *lr)
+{
+	const char *op_str;
+	char unk_op[32];
+	uint8_t *b, n;
+	int i;
+
+	if (dwarf_get_OP_name(lr->lr_atom, &op_str) !=
+	    DW_DLV_OK) {
+		snprintf(unk_op, sizeof(unk_op),
+		    "[Unknown OP: %#x]", lr->lr_atom);
+		op_str = unk_op;
+	}
+
+	printf("%s", op_str);
+
+	switch (lr->lr_atom) {
+	case DW_OP_reg0:
+	case DW_OP_reg1:
+	case DW_OP_reg2:
+	case DW_OP_reg3:
+	case DW_OP_reg4:
+	case DW_OP_reg5:
+	case DW_OP_reg6:
+	case DW_OP_reg7:
+	case DW_OP_reg8:
+	case DW_OP_reg9:
+	case DW_OP_reg10:
+	case DW_OP_reg11:
+	case DW_OP_reg12:
+	case DW_OP_reg13:
+	case DW_OP_reg14:
+	case DW_OP_reg15:
+	case DW_OP_reg16:
+	case DW_OP_reg17:
+	case DW_OP_reg18:
+	case DW_OP_reg19:
+	case DW_OP_reg20:
+	case DW_OP_reg21:
+	case DW_OP_reg22:
+	case DW_OP_reg23:
+	case DW_OP_reg24:
+	case DW_OP_reg25:
+	case DW_OP_reg26:
+	case DW_OP_reg27:
+	case DW_OP_reg28:
+	case DW_OP_reg29:
+	case DW_OP_reg30:
+	case DW_OP_reg31:
+		printf(" (%s)", dwarf_regname(re, lr->lr_atom - DW_OP_reg0));
+		break;
+
+	case DW_OP_deref:
+	case DW_OP_lit0:
+	case DW_OP_lit1:
+	case DW_OP_lit2:
+	case DW_OP_lit3:
+	case DW_OP_lit4:
+	case DW_OP_lit5:
+	case DW_OP_lit6:
+	case DW_OP_lit7:
+	case DW_OP_lit8:
+	case DW_OP_lit9:
+	case DW_OP_lit10:
+	case DW_OP_lit11:
+	case DW_OP_lit12:
+	case DW_OP_lit13:
+	case DW_OP_lit14:
+	case DW_OP_lit15:
+	case DW_OP_lit16:
+	case DW_OP_lit17:
+	case DW_OP_lit18:
+	case DW_OP_lit19:
+	case DW_OP_lit20:
+	case DW_OP_lit21:
+	case DW_OP_lit22:
+	case DW_OP_lit23:
+	case DW_OP_lit24:
+	case DW_OP_lit25:
+	case DW_OP_lit26:
+	case DW_OP_lit27:
+	case DW_OP_lit28:
+	case DW_OP_lit29:
+	case DW_OP_lit30:
+	case DW_OP_lit31:
+	case DW_OP_dup:
+	case DW_OP_drop:
+	case DW_OP_over:
+	case DW_OP_swap:
+	case DW_OP_rot:
+	case DW_OP_xderef:
+	case DW_OP_abs:
+	case DW_OP_and:
+	case DW_OP_div:
+	case DW_OP_minus:
+	case DW_OP_mod:
+	case DW_OP_mul:
+	case DW_OP_neg:
+	case DW_OP_not:
+	case DW_OP_or:
+	case DW_OP_plus:
+	case DW_OP_shl:
+	case DW_OP_shr:
+	case DW_OP_shra:
+	case DW_OP_xor:
+	case DW_OP_eq:
+	case DW_OP_ge:
+	case DW_OP_gt:
+	case DW_OP_le:
+	case DW_OP_lt:
+	case DW_OP_ne:
+	case DW_OP_nop:
+	case DW_OP_push_object_address:
+	case DW_OP_form_tls_address:
+	case DW_OP_call_frame_cfa:
+	case DW_OP_stack_value:
+	case DW_OP_GNU_push_tls_address:
+	case DW_OP_GNU_uninit:
+		break;
+
+	case DW_OP_const1u:
+	case DW_OP_pick:
+	case DW_OP_deref_size:
+	case DW_OP_xderef_size:
+	case DW_OP_const2u:
+	case DW_OP_bra:
+	case DW_OP_skip:
+	case DW_OP_const4u:
+	case DW_OP_const8u:
+	case DW_OP_constu:
+	case DW_OP_plus_uconst:
+	case DW_OP_regx:
+	case DW_OP_piece:
+		printf(": %ju", (uintmax_t)
+		    lr->lr_number);
+		break;
+
+	case DW_OP_const1s:
+	case DW_OP_const2s:
+	case DW_OP_const4s:
+	case DW_OP_const8s:
+	case DW_OP_consts:
+		printf(": %jd", (intmax_t)
+		    lr->lr_number);
+		break;
+
+	case DW_OP_breg0:
+	case DW_OP_breg1:
+	case DW_OP_breg2:
+	case DW_OP_breg3:
+	case DW_OP_breg4:
+	case DW_OP_breg5:
+	case DW_OP_breg6:
+	case DW_OP_breg7:
+	case DW_OP_breg8:
+	case DW_OP_breg9:
+	case DW_OP_breg10:
+	case DW_OP_breg11:
+	case DW_OP_breg12:
+	case DW_OP_breg13:
+	case DW_OP_breg14:
+	case DW_OP_breg15:
+	case DW_OP_breg16:
+	case DW_OP_breg17:
+	case DW_OP_breg18:
+	case DW_OP_breg19:
+	case DW_OP_breg20:
+	case DW_OP_breg21:
+	case DW_OP_breg22:
+	case DW_OP_breg23:
+	case DW_OP_breg24:
+	case DW_OP_breg25:
+	case DW_OP_breg26:
+	case DW_OP_breg27:
+	case DW_OP_breg28:
+	case DW_OP_breg29:
+	case DW_OP_breg30:
+	case DW_OP_breg31:
+		printf(" (%s): %jd",
+		    dwarf_regname(re, lr->lr_atom - DW_OP_breg0),
+		    (intmax_t) lr->lr_number);
+		break;
+
+	case DW_OP_fbreg:
+		printf(": %jd", (intmax_t)
+		    lr->lr_number);
+		break;
+
+	case DW_OP_bregx:
+		printf(": %ju (%s) %jd",
+		    (uintmax_t) lr->lr_number,
+		    dwarf_regname(re, (unsigned int) lr->lr_number),
+		    (intmax_t) lr->lr_number2);
+		break;
+
+	case DW_OP_addr:
+	case DW_OP_GNU_encoded_addr:
+		printf(": %#jx", (uintmax_t)
+		    lr->lr_number);
+		break;
+
+	case DW_OP_GNU_implicit_pointer:
+		printf(": <0x%jx> %jd", (uintmax_t) lr->lr_number,
+		    (intmax_t) lr->lr_number2);
+		break;
+
+	case DW_OP_implicit_value:
+		printf(": %ju byte block:", (uintmax_t) lr->lr_number);
+		b = (uint8_t *)(uintptr_t) lr->lr_number2;
+		for (i = 0; (Dwarf_Unsigned) i < lr->lr_number; i++)
+			printf(" %x", b[i]);
+		break;
+
+	case DW_OP_GNU_entry_value:
+		printf(": (");
+		dump_dwarf_block(re, (uint8_t *)(uintptr_t) lr->lr_number2,
+		    lr->lr_number);
+		putchar(')');
+		break;
+
+	case DW_OP_GNU_const_type:
+		printf(": <0x%jx> ", (uintmax_t) lr->lr_number);
+		b = (uint8_t *)(uintptr_t) lr->lr_number2;
+		n = *b;
+		for (i = 1; (uint8_t) i < n; i++)
+			printf(" %x", b[i]);
+		break;
+
+	case DW_OP_GNU_regval_type:
+		printf(": %ju (%s) <0x%jx>", (uintmax_t) lr->lr_number,
+		    dwarf_regname(re, (unsigned int) lr->lr_number),
+		    (uintmax_t) lr->lr_number2);
+		break;
+
+	case DW_OP_GNU_convert:
+	case DW_OP_GNU_deref_type:
+	case DW_OP_GNU_parameter_ref:
+	case DW_OP_GNU_reinterpret:
+		printf(": <0x%jx>", (uintmax_t) lr->lr_number);
+		break;
+
+	default:
+		break;
+	}
+}
+
+static void
+dump_dwarf_block(struct readelf *re, uint8_t *b, Dwarf_Unsigned len)
+{
+	Dwarf_Locdesc *llbuf;
+	Dwarf_Signed lcnt;
+	Dwarf_Error de;
+	int i;
+
+	if (dwarf_loclist_from_expr_b(re->dbg, b, len, re->cu_psize,
+	    re->cu_osize, re->cu_ver, &llbuf, &lcnt, &de) != DW_DLV_OK) {
+		warnx("dwarf_loclist_form_expr_b: %s", dwarf_errmsg(de));
+		return;
+	}
+
+	for (i = 0; (Dwarf_Half) i < llbuf->ld_cents; i++) {
+		dump_dwarf_loc(re, &llbuf->ld_s[i]);
+		if (i < llbuf->ld_cents - 1)
+			printf("; ");
+	}
+
+	dwarf_dealloc(re->dbg, llbuf->ld_s, DW_DLA_LOC_BLOCK);
+	dwarf_dealloc(re->dbg, llbuf, DW_DLA_LOCDESC);
+}
+
+static void
+dump_dwarf_loclist(struct readelf *re)
+{
+	Dwarf_Die die;
+	Dwarf_Locdesc **llbuf;
+	Dwarf_Unsigned lowpc;
+	Dwarf_Signed lcnt;
+	Dwarf_Half tag, version, pointer_size, off_size;
+	Dwarf_Error de;
+	struct loc_at *la;
+	int i, j, ret, has_content;
+
+	/* Search .debug_info section. */
+	while ((ret = dwarf_next_cu_header_b(re->dbg, NULL, &version, NULL,
+	    &pointer_size, &off_size, NULL, NULL, &de)) == DW_DLV_OK) {
+		set_cu_context(re, pointer_size, off_size, version);
+		die = NULL;
+		if (dwarf_siblingof(re->dbg, die, &die, &de) != DW_DLV_OK)
+			continue;
+		if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
+			warnx("dwarf_tag failed: %s", dwarf_errmsg(de));
+			continue;
+		}
+		/* XXX: What about DW_TAG_partial_unit? */
+		lowpc = 0;
+		if (tag == DW_TAG_compile_unit) {
+			if (dwarf_attrval_unsigned(die, DW_AT_low_pc,
+			    &lowpc, &de) != DW_DLV_OK)
+				lowpc = 0;
+		}
+
+		/* Search attributes for reference to .debug_loc section. */
+		search_loclist_at(re, die, lowpc);
+	}
+	if (ret == DW_DLV_ERROR)
+		warnx("dwarf_next_cu_header: %s", dwarf_errmsg(de));
+
+	/* Search .debug_types section. */
+	do {
+		while ((ret = dwarf_next_cu_header_c(re->dbg, 0, NULL,
+		    &version, NULL, &pointer_size, &off_size, NULL, NULL,
+		    NULL, NULL, &de)) == DW_DLV_OK) {
+			set_cu_context(re, pointer_size, off_size, version);
+			die = NULL;
+			if (dwarf_siblingof(re->dbg, die, &die, &de) !=
+			    DW_DLV_OK)
+				continue;
+			if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
+				warnx("dwarf_tag failed: %s",
+				    dwarf_errmsg(de));
+				continue;
+			}
+
+			lowpc = 0;
+			if (tag == DW_TAG_type_unit) {
+				if (dwarf_attrval_unsigned(die, DW_AT_low_pc,
+				    &lowpc, &de) != DW_DLV_OK)
+					lowpc = 0;
+			}
+
+			/*
+			 * Search attributes for reference to .debug_loc
+			 * section.
+			 */
+			search_loclist_at(re, die, lowpc);
+		}
+		if (ret == DW_DLV_ERROR)
+			warnx("dwarf_next_cu_header: %s", dwarf_errmsg(de));
+	} while (dwarf_next_types_section(re->dbg, &de) == DW_DLV_OK);
+
+	if (TAILQ_EMPTY(&lalist))
+		return;
+
+	has_content = 0;
+	TAILQ_FOREACH(la, &lalist, la_next) {
+		if ((ret = dwarf_loclist_n(la->la_at, &llbuf, &lcnt, &de)) !=
+		    DW_DLV_OK) {
+			if (ret != DW_DLV_NO_ENTRY)
+				warnx("dwarf_loclist_n failed: %s",
+				    dwarf_errmsg(de));
+			continue;
+		}
+		if (!has_content) {
+			has_content = 1;
+			printf("\nContents of section .debug_loc:\n");
+			printf("    Offset   Begin    End      Expression\n");
+		}
+		set_cu_context(re, la->la_cu_psize, la->la_cu_osize,
+		    la->la_cu_ver);
+		for (i = 0; i < lcnt; i++) {
+			printf("    %8.8jx ", (uintmax_t) la->la_off);
+			if (llbuf[i]->ld_lopc == 0 && llbuf[i]->ld_hipc == 0) {
+				printf("<End of list>\n");
+				continue;
+			}
+
+			/* TODO: handle base selection entry. */
+
+			printf("%8.8jx %8.8jx ",
+			    (uintmax_t) (la->la_lowpc + llbuf[i]->ld_lopc),
+			    (uintmax_t) (la->la_lowpc + llbuf[i]->ld_hipc));
+
+			putchar('(');
+			for (j = 0; (Dwarf_Half) j < llbuf[i]->ld_cents; j++) {
+				dump_dwarf_loc(re, &llbuf[i]->ld_s[j]);
+				if (j < llbuf[i]->ld_cents - 1)
+					printf("; ");
+			}
+			putchar(')');
+
+			if (llbuf[i]->ld_lopc == llbuf[i]->ld_hipc)
+				printf(" (start == end)");
+			putchar('\n');
+		}
+		for (i = 0; i < lcnt; i++) {
+			dwarf_dealloc(re->dbg, llbuf[i]->ld_s,
+			    DW_DLA_LOC_BLOCK);
+			dwarf_dealloc(re->dbg, llbuf[i], DW_DLA_LOCDESC);
+		}
+		dwarf_dealloc(re->dbg, llbuf, DW_DLA_LIST);
+	}
+
+	if (!has_content)
+		printf("\nSection '.debug_loc' has no debugging data.\n");
+}
+
+/*
+ * Retrieve a string using string table section index and the string offset.
+ */
+static const char*
+get_string(struct readelf *re, int strtab, size_t off)
+{
+	const char *name;
+
+	if ((name = elf_strptr(re->elf, strtab, off)) == NULL)
+		return ("");
+
+	return (name);
+}
+
+/*
+ * Retrieve the name of a symbol using the section index of the symbol
+ * table and the index of the symbol within that table.
+ */
+static const char *
+get_symbol_name(struct readelf *re, int symtab, int i)
+{
+	struct section	*s;
+	const char	*name;
+	GElf_Sym	 sym;
+	Elf_Data	*data;
+	int		 elferr;
+
+	s = &re->sl[symtab];
+	if (s->type != SHT_SYMTAB && s->type != SHT_DYNSYM)
+		return ("");
+	(void) elf_errno();
+	if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_getdata failed: %s", elf_errmsg(elferr));
+		return ("");
+	}
+	if (gelf_getsym(data, i, &sym) != &sym)
+		return ("");
+	/* Return section name for STT_SECTION symbol. */
+	if (GELF_ST_TYPE(sym.st_info) == STT_SECTION) {
+		if (sym.st_shndx < re->shnum &&
+		    re->sl[sym.st_shndx].name != NULL)
+			return (re->sl[sym.st_shndx].name);
+		return ("");
+	}
+	if (s->link >= re->shnum ||
+	    (name = elf_strptr(re->elf, s->link, sym.st_name)) == NULL)
+		return ("");
+
+	return (name);
+}
+
+static uint64_t
+get_symbol_value(struct readelf *re, int symtab, int i)
+{
+	struct section	*s;
+	GElf_Sym	 sym;
+	Elf_Data	*data;
+	int		 elferr;
+
+	s = &re->sl[symtab];
+	if (s->type != SHT_SYMTAB && s->type != SHT_DYNSYM)
+		return (0);
+	(void) elf_errno();
+	if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+		elferr = elf_errno();
+		if (elferr != 0)
+			warnx("elf_getdata failed: %s", elf_errmsg(elferr));
+		return (0);
+	}
+	if (gelf_getsym(data, i, &sym) != &sym)
+		return (0);
+
+	return (sym.st_value);
+}
+
+static void
+hex_dump(struct readelf *re)
+{
+	struct section *s;
+	Elf_Data *d;
+	uint8_t *buf;
+	size_t sz, nbytes;
+	uint64_t addr;
+	int elferr, i, j;
+
+	for (i = 1; (size_t) i < re->shnum; i++) {
+		s = &re->sl[i];
+		if (find_dumpop(re, (size_t) i, s->name, HEX_DUMP, -1) == NULL)
+			continue;
+		(void) elf_errno();
+		if ((d = elf_getdata(s->scn, NULL)) == NULL &&
+		    (d = elf_rawdata(s->scn, NULL)) == NULL) {
+			elferr = elf_errno();
+			if (elferr != 0)
+				warnx("elf_getdata failed: %s",
+				    elf_errmsg(elferr));
+			continue;
+		}
+		(void) elf_errno();
+		if (d->d_size <= 0 || d->d_buf == NULL) {
+			printf("\nSection '%s' has no data to dump.\n",
+			    s->name);
+			continue;
+		}
+		buf = d->d_buf;
+		sz = d->d_size;
+		addr = s->addr;
+		printf("\nHex dump of section '%s':\n", s->name);
+		while (sz > 0) {
+			printf("  0x%8.8jx ", (uintmax_t)addr);
+			nbytes = sz > 16? 16 : sz;
+			for (j = 0; j < 16; j++) {
+				if ((size_t)j < nbytes)
+					printf("%2.2x", buf[j]);
+				else
+					printf("  ");
+				if ((j & 3) == 3)
+					printf(" ");
+			}
+			for (j = 0; (size_t)j < nbytes; j++) {
+				if (isprint(buf[j]))
+					printf("%c", buf[j]);
+				else
+					printf(".");
+			}
+			printf("\n");
+			buf += nbytes;
+			addr += nbytes;
+			sz -= nbytes;
+		}
+	}
+}
+
+static void
+str_dump(struct readelf *re)
+{
+	struct section *s;
+	Elf_Data *d;
+	unsigned char *start, *end, *buf_end;
+	unsigned int len;
+	int i, j, elferr, found;
+
+	for (i = 1; (size_t) i < re->shnum; i++) {
+		s = &re->sl[i];
+		if (find_dumpop(re, (size_t) i, s->name, STR_DUMP, -1) == NULL)
+			continue;
+		(void) elf_errno();
+		if ((d = elf_getdata(s->scn, NULL)) == NULL &&
+		    (d = elf_rawdata(s->scn, NULL)) == NULL) {
+			elferr = elf_errno();
+			if (elferr != 0)
+				warnx("elf_getdata failed: %s",
+				    elf_errmsg(elferr));
+			continue;
+		}
+		(void) elf_errno();
+		if (d->d_size <= 0 || d->d_buf == NULL) {
+			printf("\nSection '%s' has no data to dump.\n",
+			    s->name);
+			continue;
+		}
+		buf_end = (unsigned char *) d->d_buf + d->d_size;
+		start = (unsigned char *) d->d_buf;
+		found = 0;
+		printf("\nString dump of section '%s':\n", s->name);
+		for (;;) {
+			while (start < buf_end && !isprint(*start))
+				start++;
+			if (start >= buf_end)
+				break;
+			end = start + 1;
+			while (end < buf_end && isprint(*end))
+				end++;
+			printf("  [%6lx]  ",
+			    (long) (start - (unsigned char *) d->d_buf));
+			len = end - start;
+			for (j = 0; (unsigned int) j < len; j++)
+				putchar(start[j]);
+			putchar('\n');
+			found = 1;
+			if (end >= buf_end)
+				break;
+			start = end + 1;
+		}
+		if (!found)
+			printf("  No strings found in this section.");
+		putchar('\n');
+	}
+}
+
+static void
+load_sections(struct readelf *re)
+{
+	struct section	*s;
+	const char	*name;
+	Elf_Scn		*scn;
+	GElf_Shdr	 sh;
+	size_t		 shstrndx, ndx;
+	int		 elferr;
+
+	/* Allocate storage for internal section list. */
+	if (!elf_getshnum(re->elf, &re->shnum)) {
+		warnx("elf_getshnum failed: %s", elf_errmsg(-1));
+		return;
+	}
+	if (re->sl != NULL)
+		free(re->sl);
+	if ((re->sl = calloc(re->shnum, sizeof(*re->sl))) == NULL)
+		err(EXIT_FAILURE, "calloc failed");
+
+	/* Get the index of .shstrtab section. */
+	if (!elf_getshstrndx(re->elf, &shstrndx)) {
+		warnx("elf_getshstrndx failed: %s", elf_errmsg(-1));
+		return;
+	}
+
+	if ((scn = elf_getscn(re->elf, 0)) == NULL)
+		return;
+
+	(void) elf_errno();
+	do {
+		if (gelf_getshdr(scn, &sh) == NULL) {
+			warnx("gelf_getshdr failed: %s", elf_errmsg(-1));
+			(void) elf_errno();
+			continue;
+		}
+		if ((name = elf_strptr(re->elf, shstrndx, sh.sh_name)) == NULL) {
+			(void) elf_errno();
+			name = "<no-name>";
+		}
+		if ((ndx = elf_ndxscn(scn)) == SHN_UNDEF) {
+			if ((elferr = elf_errno()) != 0) {
+				warnx("elf_ndxscn failed: %s",
+				    elf_errmsg(elferr));
+				continue;
+			}
+		}
+		if (ndx >= re->shnum) {
+			warnx("section index of '%s' out of range", name);
+			continue;
+		}
+		if (sh.sh_link >= re->shnum)
+			warnx("section link %llu of '%s' out of range",
+			    (unsigned long long)sh.sh_link, name);
+		s = &re->sl[ndx];
+		s->name = name;
+		s->scn = scn;
+		s->off = sh.sh_offset;
+		s->sz = sh.sh_size;
+		s->entsize = sh.sh_entsize;
+		s->align = sh.sh_addralign;
+		s->type = sh.sh_type;
+		s->flags = sh.sh_flags;
+		s->addr = sh.sh_addr;
+		s->link = sh.sh_link;
+		s->info = sh.sh_info;
+	} while ((scn = elf_nextscn(re->elf, scn)) != NULL);
+	elferr = elf_errno();
+	if (elferr != 0)
+		warnx("elf_nextscn failed: %s", elf_errmsg(elferr));
+}
+
+static void
+unload_sections(struct readelf *re)
+{
+
+	if (re->sl != NULL) {
+		free(re->sl);
+		re->sl = NULL;
+	}
+	re->shnum = 0;
+	re->vd_s = NULL;
+	re->vn_s = NULL;
+	re->vs_s = NULL;
+	re->vs = NULL;
+	re->vs_sz = 0;
+	if (re->ver != NULL) {
+		free(re->ver);
+		re->ver = NULL;
+		re->ver_sz = 0;
+	}
+}
+
+static void
+dump_elf(struct readelf *re)
+{
+
+	/* Fetch ELF header. No need to continue if it fails. */
+	if (gelf_getehdr(re->elf, &re->ehdr) == NULL) {
+		warnx("gelf_getehdr failed: %s", elf_errmsg(-1));
+		return;
+	}
+	if ((re->ec = gelf_getclass(re->elf)) == ELFCLASSNONE) {
+		warnx("gelf_getclass failed: %s", elf_errmsg(-1));
+		return;
+	}
+	if (re->ehdr.e_ident[EI_DATA] == ELFDATA2MSB) {
+		re->dw_read = _read_msb;
+		re->dw_decode = _decode_msb;
+	} else {
+		re->dw_read = _read_lsb;
+		re->dw_decode = _decode_lsb;
+	}
+
+	if (re->options & ~RE_H)
+		load_sections(re);
+	if ((re->options & RE_VV) || (re->options & RE_S))
+		search_ver(re);
+	if (re->options & RE_H)
+		dump_ehdr(re);
+	if (re->options & RE_L)
+		dump_phdr(re);
+	if (re->options & RE_SS)
+		dump_shdr(re);
+	if (re->options & RE_G)
+		dump_section_groups(re);
+	if (re->options & RE_D)
+		dump_dynamic(re);
+	if (re->options & RE_R)
+		dump_reloc(re);
+	if (re->options & RE_S)
+		dump_symtabs(re);
+	if (re->options & RE_N)
+		dump_notes(re);
+	if (re->options & RE_II)
+		dump_hash(re);
+	if (re->options & RE_X)
+		hex_dump(re);
+	if (re->options & RE_P)
+		str_dump(re);
+	if (re->options & RE_VV)
+		dump_ver(re);
+	if (re->options & RE_AA)
+		dump_arch_specific_info(re);
+	if (re->options & RE_W)
+		dump_dwarf(re);
+	if (re->options & ~RE_H)
+		unload_sections(re);
+}
+
+static void
+dump_dwarf(struct readelf *re)
+{
+	struct loc_at *la, *_la;
+	Dwarf_Error de;
+	int error;
+
+	if (dwarf_elf_init(re->elf, DW_DLC_READ, NULL, NULL, &re->dbg, &de)) {
+		if ((error = dwarf_errno(de)) != DW_DLE_DEBUG_INFO_NULL)
+			errx(EXIT_FAILURE, "dwarf_elf_init failed: %s",
+			    dwarf_errmsg(de));
+		return;
+	}
+
+	if (re->dop & DW_A)
+		dump_dwarf_abbrev(re);
+	if (re->dop & DW_L)
+		dump_dwarf_line(re);
+	if (re->dop & DW_LL)
+		dump_dwarf_line_decoded(re);
+	if (re->dop & DW_I) {
+		dump_dwarf_info(re, 0);
+		dump_dwarf_info(re, 1);
+	}
+	if (re->dop & DW_P)
+		dump_dwarf_pubnames(re);
+	if (re->dop & DW_R)
+		dump_dwarf_aranges(re);
+	if (re->dop & DW_RR)
+		dump_dwarf_ranges(re);
+	if (re->dop & DW_M)
+		dump_dwarf_macinfo(re);
+	if (re->dop & DW_F)
+		dump_dwarf_frame(re, 0);
+	else if (re->dop & DW_FF)
+		dump_dwarf_frame(re, 1);
+	if (re->dop & DW_S)
+		dump_dwarf_str(re);
+	if (re->dop & DW_O)
+		dump_dwarf_loclist(re);
+
+	TAILQ_FOREACH_SAFE(la, &lalist, la_next, _la) {
+		TAILQ_REMOVE(&lalist, la, la_next);
+		free(la);
+	}
+
+	dwarf_finish(re->dbg, &de);
+}
+
+static void
+dump_ar(struct readelf *re, int fd)
+{
+	Elf_Arsym *arsym;
+	Elf_Arhdr *arhdr;
+	Elf_Cmd cmd;
+	Elf *e;
+	size_t sz;
+	off_t off;
+	int i;
+
+	re->ar = re->elf;
+
+	if (re->options & RE_C) {
+		if ((arsym = elf_getarsym(re->ar, &sz)) == NULL) {
+			warnx("elf_getarsym() failed: %s", elf_errmsg(-1));
+			goto process_members;
+		}
+		printf("Index of archive %s: (%ju entries)\n", re->filename,
+		    (uintmax_t) sz - 1);
+		off = 0;
+		for (i = 0; (size_t) i < sz; i++) {
+			if (arsym[i].as_name == NULL)
+				break;
+			if (arsym[i].as_off != off) {
+				off = arsym[i].as_off;
+				if (elf_rand(re->ar, off) != off) {
+					warnx("elf_rand() failed: %s",
+					    elf_errmsg(-1));
+					continue;
+				}
+				if ((e = elf_begin(fd, ELF_C_READ, re->ar)) ==
+				    NULL) {
+					warnx("elf_begin() failed: %s",
+					    elf_errmsg(-1));
+					continue;
+				}
+				if ((arhdr = elf_getarhdr(e)) == NULL) {
+					warnx("elf_getarhdr() failed: %s",
+					    elf_errmsg(-1));
+					elf_end(e);
+					continue;
+				}
+				printf("Binary %s(%s) contains:\n",
+				    re->filename, arhdr->ar_name);
+			}
+			printf("\t%s\n", arsym[i].as_name);
+		}
+		if (elf_rand(re->ar, SARMAG) != SARMAG) {
+			warnx("elf_rand() failed: %s", elf_errmsg(-1));
+			return;
+		}
+	}
+
+process_members:
+
+	if ((re->options & ~RE_C) == 0)
+		return;
+
+	cmd = ELF_C_READ;
+	while ((re->elf = elf_begin(fd, cmd, re->ar)) != NULL) {
+		if ((arhdr = elf_getarhdr(re->elf)) == NULL) {
+			warnx("elf_getarhdr() failed: %s", elf_errmsg(-1));
+			goto next_member;
+		}
+		if (strcmp(arhdr->ar_name, "/") == 0 ||
+		    strcmp(arhdr->ar_name, "//") == 0 ||
+		    strcmp(arhdr->ar_name, "__.SYMDEF") == 0)
+			goto next_member;
+		printf("\nFile: %s(%s)\n", re->filename, arhdr->ar_name);
+		dump_elf(re);
+
+	next_member:
+		cmd = elf_next(re->elf);
+		elf_end(re->elf);
+	}
+	re->elf = re->ar;
+}
+
+static void
+dump_object(struct readelf *re)
+{
+	int fd;
+
+	if ((fd = open(re->filename, O_RDONLY)) == -1) {
+		warn("open %s failed", re->filename);
+		return;
+	}
+
+	if ((re->flags & DISPLAY_FILENAME) != 0)
+		printf("\nFile: %s\n", re->filename);
+
+	if ((re->elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
+		warnx("elf_begin() failed: %s", elf_errmsg(-1));
+		return;
+	}
+
+	switch (elf_kind(re->elf)) {
+	case ELF_K_NONE:
+		warnx("Not an ELF file.");
+		return;
+	case ELF_K_ELF:
+		dump_elf(re);
+		break;
+	case ELF_K_AR:
+		dump_ar(re, fd);
+		break;
+	default:
+		warnx("Internal: libelf returned unknown elf kind.");
+		return;
+	}
+
+	elf_end(re->elf);
+}
+
+static void
+add_dumpop(struct readelf *re, size_t si, const char *sn, int op, int t)
+{
+	struct dumpop *d;
+
+	if ((d = find_dumpop(re, si, sn, -1, t)) == NULL) {
+		if ((d = calloc(1, sizeof(*d))) == NULL)
+			err(EXIT_FAILURE, "calloc failed");
+		if (t == DUMP_BY_INDEX)
+			d->u.si = si;
+		else
+			d->u.sn = sn;
+		d->type = t;
+		d->op = op;
+		STAILQ_INSERT_TAIL(&re->v_dumpop, d, dumpop_list);
+	} else
+		d->op |= op;
+}
+
+static struct dumpop *
+find_dumpop(struct readelf *re, size_t si, const char *sn, int op, int t)
+{
+	struct dumpop *d;
+
+	STAILQ_FOREACH(d, &re->v_dumpop, dumpop_list) {
+		if ((op == -1 || op & d->op) &&
+		    (t == -1 || (unsigned) t == d->type)) {
+			if ((d->type == DUMP_BY_INDEX && d->u.si == si) ||
+			    (d->type == DUMP_BY_NAME && !strcmp(d->u.sn, sn)))
+				return (d);
+		}
+	}
+
+	return (NULL);
+}
+
+static struct {
+	const char *ln;
+	char sn;
+	int value;
+} dwarf_op[] = {
+	{"rawline", 'l', DW_L},
+	{"decodedline", 'L', DW_LL},
+	{"info", 'i', DW_I},
+	{"abbrev", 'a', DW_A},
+	{"pubnames", 'p', DW_P},
+	{"aranges", 'r', DW_R},
+	{"ranges", 'r', DW_R},
+	{"Ranges", 'R', DW_RR},
+	{"macro", 'm', DW_M},
+	{"frames", 'f', DW_F},
+	{"frames-interp", 'F', DW_FF},
+	{"str", 's', DW_S},
+	{"loc", 'o', DW_O},
+	{NULL, 0, 0}
+};
+
+static void
+parse_dwarf_op_short(struct readelf *re, const char *op)
+{
+	int i;
+
+	if (op == NULL) {
+		re->dop |= DW_DEFAULT_OPTIONS;
+		return;
+	}
+
+	for (; *op != '\0'; op++) {
+		for (i = 0; dwarf_op[i].ln != NULL; i++) {
+			if (dwarf_op[i].sn == *op) {
+				re->dop |= dwarf_op[i].value;
+				break;
+			}
+		}
+	}
+}
+
+static void
+parse_dwarf_op_long(struct readelf *re, const char *op)
+{
+	char *p, *token, *bp;
+	int i;
+
+	if (op == NULL) {
+		re->dop |= DW_DEFAULT_OPTIONS;
+		return;
+	}
+
+	if ((p = strdup(op)) == NULL)
+		err(EXIT_FAILURE, "strdup failed");
+	bp = p;
+
+	while ((token = strsep(&p, ",")) != NULL) {
+		for (i = 0; dwarf_op[i].ln != NULL; i++) {
+			if (!strcmp(token, dwarf_op[i].ln)) {
+				re->dop |= dwarf_op[i].value;
+				break;
+			}
+		}
+	}
+
+	free(bp);
+}
+
+static uint64_t
+_read_lsb(Elf_Data *d, uint64_t *offsetp, int bytes_to_read)
+{
+	uint64_t ret;
+	uint8_t *src;
+
+	src = (uint8_t *) d->d_buf + *offsetp;
+
+	ret = 0;
+	switch (bytes_to_read) {
+	case 8:
+		ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40;
+		ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56;
+		/* FALLTHROUGH */
+	case 4:
+		ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24;
+		/* FALLTHROUGH */
+	case 2:
+		ret |= ((uint64_t) src[1]) << 8;
+		/* FALLTHROUGH */
+	case 1:
+		ret |= src[0];
+		break;
+	default:
+		return (0);
+	}
+
+	*offsetp += bytes_to_read;
+
+	return (ret);
+}
+
+static uint64_t
+_read_msb(Elf_Data *d, uint64_t *offsetp, int bytes_to_read)
+{
+	uint64_t ret;
+	uint8_t *src;
+
+	src = (uint8_t *) d->d_buf + *offsetp;
+
+	switch (bytes_to_read) {
+	case 1:
+		ret = src[0];
+		break;
+	case 2:
+		ret = src[1] | ((uint64_t) src[0]) << 8;
+		break;
+	case 4:
+		ret = src[3] | ((uint64_t) src[2]) << 8;
+		ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24;
+		break;
+	case 8:
+		ret = src[7] | ((uint64_t) src[6]) << 8;
+		ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24;
+		ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40;
+		ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56;
+		break;
+	default:
+		return (0);
+	}
+
+	*offsetp += bytes_to_read;
+
+	return (ret);
+}
+
+static uint64_t
+_decode_lsb(uint8_t **data, int bytes_to_read)
+{
+	uint64_t ret;
+	uint8_t *src;
+
+	src = *data;
+
+	ret = 0;
+	switch (bytes_to_read) {
+	case 8:
+		ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40;
+		ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56;
+		/* FALLTHROUGH */
+	case 4:
+		ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24;
+		/* FALLTHROUGH */
+	case 2:
+		ret |= ((uint64_t) src[1]) << 8;
+		/* FALLTHROUGH */
+	case 1:
+		ret |= src[0];
+		break;
+	default:
+		return (0);
+	}
+
+	*data += bytes_to_read;
+
+	return (ret);
+}
+
+static uint64_t
+_decode_msb(uint8_t **data, int bytes_to_read)
+{
+	uint64_t ret;
+	uint8_t *src;
+
+	src = *data;
+
+	ret = 0;
+	switch (bytes_to_read) {
+	case 1:
+		ret = src[0];
+		break;
+	case 2:
+		ret = src[1] | ((uint64_t) src[0]) << 8;
+		break;
+	case 4:
+		ret = src[3] | ((uint64_t) src[2]) << 8;
+		ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24;
+		break;
+	case 8:
+		ret = src[7] | ((uint64_t) src[6]) << 8;
+		ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24;
+		ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40;
+		ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56;
+		break;
+	default:
+		return (0);
+		break;
+	}
+
+	*data += bytes_to_read;
+
+	return (ret);
+}
+
+static int64_t
+_decode_sleb128(uint8_t **dp, uint8_t *dpe)
+{
+	int64_t ret = 0;
+	uint8_t b = 0;
+	int shift = 0;
+
+	uint8_t *src = *dp;
+
+	do {
+		if (src >= dpe)
+			break;
+		b = *src++;
+		ret |= ((b & 0x7f) << shift);
+		shift += 7;
+	} while ((b & 0x80) != 0);
+
+	if (shift < 32 && (b & 0x40) != 0)
+		ret |= (-1 << shift);
+
+	*dp = src;
+
+	return (ret);
+}
+
+static uint64_t
+_decode_uleb128(uint8_t **dp, uint8_t *dpe)
+{
+	uint64_t ret = 0;
+	uint8_t b;
+	int shift = 0;
+
+	uint8_t *src = *dp;
+
+	do {
+		if (src >= dpe)
+			break;
+		b = *src++;
+		ret |= ((b & 0x7f) << shift);
+		shift += 7;
+	} while ((b & 0x80) != 0);
+
+	*dp = src;
+
+	return (ret);
+}
+
+static void
+readelf_version(void)
+{
+	(void) printf("%s (%s)\n", ELFTC_GETPROGNAME(),
+	    elftc_version());
+	exit(EXIT_SUCCESS);
+}
+
+#define	USAGE_MESSAGE	"\
+Usage: %s [options] file...\n\
+  Display information about ELF objects and ar(1) archives.\n\n\
+  Options:\n\
+  -a | --all               Equivalent to specifying options '-dhIlrsASV'.\n\
+  -c | --archive-index     Print the archive symbol table for archives.\n\
+  -d | --dynamic           Print the contents of SHT_DYNAMIC sections.\n\
+  -e | --headers           Print all headers in the object.\n\
+  -g | --section-groups    Print the contents of the section groups.\n\
+  -h | --file-header       Print the file header for the object.\n\
+  -l | --program-headers   Print the PHDR table for the object.\n\
+  -n | --notes             Print the contents of SHT_NOTE sections.\n\
+  -p INDEX | --string-dump=INDEX\n\
+                           Print the contents of section at index INDEX.\n\
+  -r | --relocs            Print relocation information.\n\
+  -s | --syms | --symbols  Print symbol tables.\n\
+  -t | --section-details   Print additional information about sections.\n\
+  -v | --version           Print a version identifier and exit.\n\
+  -w[afilmoprsFLR] | --debug-dump={abbrev,aranges,decodedline,frames,\n\
+                               frames-interp,info,loc,macro,pubnames,\n\
+                               ranges,Ranges,rawline,str}\n\
+                           Display DWARF information.\n\
+  -x INDEX | --hex-dump=INDEX\n\
+                           Display contents of a section as hexadecimal.\n\
+  -A | --arch-specific     (accepted, but ignored)\n\
+  -D | --use-dynamic       Print the symbol table specified by the DT_SYMTAB\n\
+                           entry in the \".dynamic\" section.\n\
+  -H | --help              Print a help message.\n\
+  -I | --histogram         Print information on bucket list lengths for \n\
+                           hash sections.\n\
+  -N | --full-section-name (accepted, but ignored)\n\
+  -S | --sections | --section-headers\n\
+                           Print information about section headers.\n\
+  -V | --version-info      Print symbol versoning information.\n\
+  -W | --wide              Print information without wrapping long lines.\n"
+
+
+static void
+readelf_usage(int status)
+{
+	fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
+	exit(status);
+}
+
+int
+main(int argc, char **argv)
+{
+	struct readelf	*re, re_storage;
+	unsigned long	 si;
+	int		 opt, i;
+	char		*ep;
+
+	re = &re_storage;
+	memset(re, 0, sizeof(*re));
+	STAILQ_INIT(&re->v_dumpop);
+
+	while ((opt = getopt_long(argc, argv, "AacDdegHhIi:lNnp:rSstuVvWw::x:",
+	    longopts, NULL)) != -1) {
+		switch(opt) {
+		case '?':
+			readelf_usage(EXIT_SUCCESS);
+			break;
+		case 'A':
+			re->options |= RE_AA;
+			break;
+		case 'a':
+			re->options |= RE_AA | RE_D | RE_G | RE_H | RE_II |
+			    RE_L | RE_R | RE_SS | RE_S | RE_VV;
+			break;
+		case 'c':
+			re->options |= RE_C;
+			break;
+		case 'D':
+			re->options |= RE_DD;
+			break;
+		case 'd':
+			re->options |= RE_D;
+			break;
+		case 'e':
+			re->options |= RE_H | RE_L | RE_SS;
+			break;
+		case 'g':
+			re->options |= RE_G;
+			break;
+		case 'H':
+			readelf_usage(EXIT_SUCCESS);
+			break;
+		case 'h':
+			re->options |= RE_H;
+			break;
+		case 'I':
+			re->options |= RE_II;
+			break;
+		case 'i':
+			/* Not implemented yet. */
+			break;
+		case 'l':
+			re->options |= RE_L;
+			break;
+		case 'N':
+			re->options |= RE_NN;
+			break;
+		case 'n':
+			re->options |= RE_N;
+			break;
+		case 'p':
+			re->options |= RE_P;
+			si = strtoul(optarg, &ep, 10);
+			if (*ep == '\0')
+				add_dumpop(re, (size_t) si, NULL, STR_DUMP,
+				    DUMP_BY_INDEX);
+			else
+				add_dumpop(re, 0, optarg, STR_DUMP,
+				    DUMP_BY_NAME);
+			break;
+		case 'r':
+			re->options |= RE_R;
+			break;
+		case 'S':
+			re->options |= RE_SS;
+			break;
+		case 's':
+			re->options |= RE_S;
+			break;
+		case 't':
+			re->options |= RE_T;
+			break;
+		case 'u':
+			re->options |= RE_U;
+			break;
+		case 'V':
+			re->options |= RE_VV;
+			break;
+		case 'v':
+			readelf_version();
+			break;
+		case 'W':
+			re->options |= RE_WW;
+			break;
+		case 'w':
+			re->options |= RE_W;
+			parse_dwarf_op_short(re, optarg);
+			break;
+		case 'x':
+			re->options |= RE_X;
+			si = strtoul(optarg, &ep, 10);
+			if (*ep == '\0')
+				add_dumpop(re, (size_t) si, NULL, HEX_DUMP,
+				    DUMP_BY_INDEX);
+			else
+				add_dumpop(re, 0, optarg, HEX_DUMP,
+				    DUMP_BY_NAME);
+			break;
+		case OPTION_DEBUG_DUMP:
+			re->options |= RE_W;
+			parse_dwarf_op_long(re, optarg);
+		}
+	}
+
+	argv += optind;
+	argc -= optind;
+
+	if (argc == 0 || re->options == 0)
+		readelf_usage(EXIT_FAILURE);
+
+	if (argc > 1)
+		re->flags |= DISPLAY_FILENAME;
+
+	if (elf_version(EV_CURRENT) == EV_NONE)
+		errx(EXIT_FAILURE, "ELF library initialization failed: %s",
+		    elf_errmsg(-1));
+
+	for (i = 0; i < argc; i++) {
+		re->filename = argv[i];
+		dump_object(re);
+	}
+
+	exit(EXIT_SUCCESS);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/size/Makefile	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,11 @@
+# $Id: Makefile 2043 2011-10-23 14:49:16Z jkoshy $
+
+TOP=	..
+
+PROG=   size
+WARNS?= 6
+LDADD=  -lelftc -lelf
+DPADD=	${LIBELFTC} ${LIBELF}
+
+.include "${TOP}/mk/elftoolchain.prog.mk"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/size/os.NetBSD.mk	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,2 @@
+# TODO(#511): Revert after the source tree is -Wconversion clean.
+WARNS=5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/size/size.1	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,257 @@
+.\" Copyright (c) 2007 S.Sam Arun Raj
+.\" Copyright (c) 2008,2011 Joseph Koshy
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: size.1 3195 2015-05-12 17:22:19Z emaste $
+.\"
+.Dd August 25, 2011
+.Dt SIZE 1
+.Os
+.Sh NAME
+.Nm size
+.Nd "display section sizes and total size of ELF objects"
+.Sh SYNOPSIS
+.Nm
+.Op Fl -format= Ns Ar format
+.Op Fl -help
+.Op Fl -radix= Ns Ar radix
+.Op Fl -totals
+.Op Fl -version
+.Op Fl ABVdhotx
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility
+lists the sizes of ELF sections, and optionally the total size, for
+each input
+.Ar file
+specified on the command line.
+The
+.Nm
+utility can operate on ELF objects, on
+.Xr ar 1
+archives containing ELF objects, and on core dumps.
+If no file name is specified on the command-line,
+.Pa a.out
+is assumed.
+.Pp
+The
+.Nm
+utility recognized the following options:
+.Bl -tag -width indent
+.It Fl -format= Ns Ar format
+Display output using the format specified by argument
+.Ar format .
+Supported values for this argument are:
+.Sq berkeley
+and
+.Sq sysv .
+The default output format is
+.Sq berkeley .
+See
+.Sx Display Formats
+below for more information.
+.It Fl -help
+Display a help message and exit.
+.It Fl -radix= Ns Ar radix
+Display numeric values using the radix specified by argument
+.Ar radix .
+Supported values for
+.Ar radix
+are 8, 10 and 16.
+The default radix is 10.
+.It Fl -totals
+Shows cumulative totals of section sizes from all objects.
+This option is ignored for System V style output.
+.It Fl -version
+Display a version identifier and exit.
+.It Fl A
+Equivalent to specifying option
+.Fl -format= Ns Ar sysv .
+.It Fl B
+Equivalent to specifying option
+.Fl -format= Ns Ar berkeley .
+.It Fl V
+Equivalent to specifying option
+.Fl -version .
+.It Fl d
+Equivalent to specifying option
+.Fl -radix= Ns Ar 10 .
+.It Fl h
+Equivalent to specifying option
+.Fl -help .
+.It Fl o
+Equivalent to specifying option
+.Fl -radix= Ns Ar 8 .
+.It Fl t
+Equivalent to specifying option
+.Fl -totals .
+.It Fl x
+Equivalent to specifying option
+.Fl -radix= Ns Ar 16 .
+.El
+.Sh DISPLAY FORMATS
+.Ss Berkeley Style Output
+If
+.Sq berkeley
+style output is in effect, an initial header line naming fields will
+be output, followed by one line of output for each ELF object specified
+on the command line or found in an archive.
+.Pp
+Each line will contain the following whitespace separated fields
+in order:
+.Bl -enum -compact
+.It
+The size of the text segment in the object.
+.It
+The size of the data segment in the object.
+.It
+The size of the
+.Sq bss
+segment in the object.
+.It
+The total size of the object in either decimal or octal.
+Decimal output is used if the specified output radix for numeric values
+is 10 or 16.
+Octal output is used if the radix being used for numeric values
+is 8.
+.It
+The total size of the object in hexadecimal.
+.It
+The file name of the object.
+.El
+.Pp
+If option
+.Fl -totals
+was specified, an additional line in the same format as above will be
+output at the end containing the sum of the respective fields.
+The file name field for the line will contain the string
+.Sq (TOTALS) .
+.Ss System V Style Output
+If System V style output is selected,
+.Nm
+will output the following information for each object:
+.Bl -enum -compact
+.It
+The name of the object followed by a colon.
+.It
+A header line containing the names of fields of subsequent lines.
+.It
+One line per section present in the object.
+Each line has three fields:
+.Bl -enum -compact
+.It
+The name of the section.
+.It
+Its size, in the selected radix for numeric values.
+.It
+The address associated with the section, in the selected numeric radix.
+.El
+.It
+A line whose section name field contains the string
+.Sq Total
+and whose size field contains the sum of all reported section sizes.
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+To display the section sizes for
+.Pa /bin/ls
+use:
+.Bd -literal
+$ size /bin/ls
+text       data       bss        dec        hex        filename
+20975      540        392        21907      5593        /bin/ls
+.Ed
+.Pp
+To display sizes and total for
+.Pa /bin/ls
+and
+.Pa /bin/dd
+in hexadecimal, use:
+.Bd -literal
+$ size -tx /bin/ls /bin/dd
+text       data       bss        dec        hex        filename
+0x51ef     0x21c      0x188      21907      5593        /bin/ls
+0x3df5     0x170      0x200      16741      4165        /bin/dd
+0x8fe4     0x38c      0x388      38648      96f8       (TOTALS)
+.Ed
+.Pp
+To display section sizes for
+.Pa /bin/ls
+in System V format use:
+.Bd -literal
+$ size -A /bin/ls
+/bin/ls  :
+section            size       addr
+\&.interp            21         4194704
+\&.note.ABI-tag      24         4194728
+\&.hash              624        4194752
+\&.dynsym            2088       4195376
+\&.dynstr            810        4197464
+\&.rela.dyn          120        4198280
+\&.rela.plt          1656       4198400
+\&.init              19         4200056
+\&.plt               1120       4200076
+\&.text              15224      4201200
+\&.fini              14         4216424
+\&.rodata            1472       4216448
+\&.data              80         5267456
+\&.eh_frame          1624       5267536
+\&.dynamic           384        5269160
+\&.ctors             16         5269544
+\&.dtors             16         5269560
+\&.jcr               8          5269576
+\&.got               576        5269584
+\&.bss               528        5270176
+\&.comment           686        0
+Total              27110
+.Ed
+.Sh SEE ALSO
+.Xr ar 1 ,
+.Xr nm 1 ,
+.Xr objdump 1 ,
+.Xr readelf 1 ,
+.Xr strings 1 ,
+.Xr elf 3 ,
+.Xr gelf 3
+.Rs
+.%A "AT&T Unix Systems Labs"
+.%T "System V Application Binary Interface"
+.%O http://www.sco.com/developers/gabi/
+.Re
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.At v6 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+utility was re-written by
+.An S. Sam Arun Raj Aq Mt samarunraj@gmail.com
+This manual page was written by
+.An S. Sam Arun Raj Aq Mt samarunraj@gmail.com
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/size/size.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,929 @@
+/*-
+ * Copyright (c) 2007 S.Sam Arun Raj
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <err.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <getopt.h>
+#include <libelftc.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "_elftc.h"
+
+ELFTC_VCSID("$Id: size.c 3458 2016-05-09 15:01:25Z emaste $");
+
+#define	BUF_SIZE			1024
+#define	ELF_ALIGN(val,x) (((val)+(x)-1) & ~((x)-1))
+#define	SIZE_VERSION_STRING		"size 1.0"
+
+enum return_code {
+	RETURN_OK,
+	RETURN_NOINPUT,
+	RETURN_DATAERR,
+	RETURN_USAGE
+};
+
+enum output_style {
+	STYLE_BERKELEY,
+	STYLE_SYSV
+};
+
+enum radix_style {
+	RADIX_OCTAL,
+	RADIX_DECIMAL,
+	RADIX_HEX
+};
+
+static uint64_t bss_size, data_size, text_size, total_size;
+static uint64_t bss_size_total, data_size_total, text_size_total;
+static int show_totals;
+static int size_option;
+static enum radix_style radix = RADIX_DECIMAL;
+static enum output_style style = STYLE_BERKELEY;
+static const char *default_args[2] = { "a.out", NULL };
+
+static struct {
+	int row;
+	int col;
+	int *width;
+	char ***tbl;
+} *tb;
+
+enum {
+	OPT_FORMAT,
+	OPT_RADIX
+};
+
+static struct option size_longopts[] = {
+	{ "format",	required_argument, &size_option, OPT_FORMAT },
+	{ "help",	no_argument,	NULL,	'h' },
+	{ "radix",	required_argument, &size_option, OPT_RADIX },
+	{ "totals",	no_argument,	NULL,	't' },
+	{ "version",	no_argument,	NULL,	'V' },
+	{ NULL, 0, NULL, 0 }  
+};
+
+static void	berkeley_calc(GElf_Shdr *);
+static void	berkeley_footer(const char *, const char *, const char *);
+static void	berkeley_header(void);
+static void	berkeley_totals(void);
+static int	handle_core(char const *, Elf *elf, GElf_Ehdr *);
+static void	handle_core_note(Elf *, GElf_Ehdr *, GElf_Phdr *, char **);
+static int	handle_elf(char const *);
+static void	handle_phdr(Elf *, GElf_Ehdr *, GElf_Phdr *, uint32_t,
+		    const char *);
+static void	show_version(void);
+static void	sysv_header(const char *, Elf_Arhdr *);
+static void	sysv_footer(void);
+static void	sysv_calc(Elf *, GElf_Ehdr *, GElf_Shdr *);
+static void	usage(void);
+static void	tbl_new(int);
+static void	tbl_print(const char *, int);
+static void	tbl_print_num(uint64_t, enum radix_style, int);
+static void	tbl_append(void);
+static void	tbl_flush(void);
+
+/*
+ * size utility using elf(3) and gelf(3) API to list section sizes and
+ * total in elf files. Supports only elf files (core dumps in elf
+ * included) that can be opened by libelf, other formats are not supported.
+ */
+int
+main(int argc, char **argv)
+{
+	int ch, r, rc;
+	const char **files, *fn;
+
+	rc = RETURN_OK;
+
+	if (elf_version(EV_CURRENT) == EV_NONE)
+		errx(EXIT_FAILURE, "ELF library initialization failed: %s",
+		    elf_errmsg(-1));
+
+	while ((ch = getopt_long(argc, argv, "ABVdhotx", size_longopts,
+	    NULL)) != -1)
+		switch((char)ch) {
+		case 'A':
+			style = STYLE_SYSV;
+			break;
+		case 'B':
+			style = STYLE_BERKELEY;
+			break;
+		case 'V':
+			show_version();
+			break;
+		case 'd':
+			radix = RADIX_DECIMAL;
+			break;
+		case 'o':
+			radix = RADIX_OCTAL;
+			break;
+		case 't':
+			show_totals = 1;
+			break;
+		case 'x':
+			radix = RADIX_HEX;
+			break;
+		case 0:
+			switch (size_option) {
+			case OPT_FORMAT:
+				if (*optarg == 's' || *optarg == 'S')
+					style = STYLE_SYSV;
+				else if (*optarg == 'b' || *optarg == 'B')
+					style = STYLE_BERKELEY;
+				else {
+					warnx("unrecognized format \"%s\".",
+					      optarg);
+					usage();
+				}
+				break;
+			case OPT_RADIX:
+				r = strtol(optarg, NULL, 10);
+				if (r == 8)
+					radix = RADIX_OCTAL;
+				else if (r == 10)
+					radix = RADIX_DECIMAL;
+				else if (r == 16)
+					radix = RADIX_HEX;
+				else {
+					warnx("unsupported radix \"%s\".",
+					      optarg);
+					usage();
+				}
+				break;
+			default:
+				err(EXIT_FAILURE, "Error in option handling.");
+				/*NOTREACHED*/
+			}
+			break;
+		case 'h':
+		case '?':
+		default:
+			usage();
+			/* NOTREACHED */
+		}
+	argc -= optind;
+	argv += optind;
+
+	files = (argc == 0) ? default_args : (void *) argv;
+
+	while ((fn = *files) != NULL) {
+		rc = handle_elf(fn);
+		if (rc != RETURN_OK)
+			warnx(rc == RETURN_NOINPUT ?
+			      "'%s': No such file" :
+			      "%s: File format not recognized", fn);
+		files++;
+	}
+	if (style == STYLE_BERKELEY) {
+		if (show_totals)
+			berkeley_totals();
+		tbl_flush();
+	}
+        return (rc);
+}
+
+static Elf_Data *
+xlatetom(Elf *elf, GElf_Ehdr *elfhdr, void *_src, void *_dst,
+    Elf_Type type, size_t size)
+{
+	Elf_Data src, dst;
+
+	src.d_buf = _src;
+	src.d_type = type;
+	src.d_version = elfhdr->e_version;
+	src.d_size = size;
+	dst.d_buf = _dst;
+	dst.d_version = elfhdr->e_version;
+	dst.d_size = size;
+	return (gelf_xlatetom(elf, &dst, &src, elfhdr->e_ident[EI_DATA]));
+}
+
+#define NOTE_OFFSET_32(nhdr, namesz, offset) 			\
+	((char *)nhdr + sizeof(Elf32_Nhdr) +			\
+	    ELF_ALIGN((int32_t)namesz, 4) + offset)
+
+#define NOTE_OFFSET_64(nhdr, namesz, offset) 			\
+	((char *)nhdr + sizeof(Elf32_Nhdr) +			\
+	    ELF_ALIGN((int32_t)namesz, 8) + offset)
+
+#define PID32(nhdr, namesz, offset) 				\
+	(pid_t)*((int *)((uintptr_t)NOTE_OFFSET_32(nhdr,	\
+	    namesz, offset)));
+
+#define PID64(nhdr, namesz, offset) 				\
+	(pid_t)*((int *)((uintptr_t)NOTE_OFFSET_64(nhdr,	\
+	    namesz, offset)));
+
+#define NEXT_NOTE(elfhdr, descsz, namesz, offset) do {		\
+	if (elfhdr->e_ident[EI_CLASS] == ELFCLASS32) { 		\
+		offset += ELF_ALIGN((int32_t)descsz, 4) +	\
+		    sizeof(Elf32_Nhdr) + 			\
+			ELF_ALIGN((int32_t)namesz, 4); 		\
+	} else {						\
+		offset += ELF_ALIGN((int32_t)descsz, 8) + 	\
+		    sizeof(Elf32_Nhdr) + 			\
+		        ELF_ALIGN((int32_t)namesz, 8); 		\
+	}							\
+} while (0)
+
+/*
+ * Parse individual note entries inside a PT_NOTE segment.
+ */
+static void
+handle_core_note(Elf *elf, GElf_Ehdr *elfhdr, GElf_Phdr *phdr,
+    char **cmd_line)
+{
+	size_t max_size, segment_end;
+	uint64_t raw_size;
+	GElf_Off offset;
+	static pid_t pid;
+	uintptr_t ver;
+	Elf32_Nhdr *nhdr, nhdr_l;
+	static int reg_pseudo = 0, reg2_pseudo = 0 /*, regxfp_pseudo = 0*/;
+	char buf[BUF_SIZE], *data, *name;
+
+ 	if (elf == NULL || elfhdr == NULL || phdr == NULL)
+		return;
+
+	data = elf_rawfile(elf, &max_size);
+	offset = phdr->p_offset;
+	if (offset >= max_size || phdr->p_filesz > max_size - offset) {
+		warnx("invalid PHDR offset");
+		return;
+	}
+	segment_end = phdr->p_offset + phdr->p_filesz;
+
+	while (data != NULL && offset + sizeof(Elf32_Nhdr) < segment_end) {
+		nhdr = (Elf32_Nhdr *)(uintptr_t)((char*)data + offset);
+		memset(&nhdr_l, 0, sizeof(Elf32_Nhdr));
+		if (!xlatetom(elf, elfhdr, &nhdr->n_type, &nhdr_l.n_type,
+			ELF_T_WORD, sizeof(Elf32_Word)) ||
+		    !xlatetom(elf, elfhdr, &nhdr->n_descsz, &nhdr_l.n_descsz,
+			ELF_T_WORD, sizeof(Elf32_Word)) ||
+		    !xlatetom(elf, elfhdr, &nhdr->n_namesz, &nhdr_l.n_namesz,
+			ELF_T_WORD, sizeof(Elf32_Word)))
+			break;
+
+		if (offset + sizeof(Elf32_Nhdr) +
+		    ELF_ALIGN(nhdr_l.n_namesz, 4) +
+		    ELF_ALIGN(nhdr_l.n_descsz, 4) >= segment_end) {
+			warnx("invalid note header");
+			return;
+		}
+
+		name = (char *)((char *)nhdr + sizeof(Elf32_Nhdr));
+		switch (nhdr_l.n_type) {
+		case NT_PRSTATUS: {
+			raw_size = 0;
+			if (elfhdr->e_ident[EI_OSABI] == ELFOSABI_FREEBSD &&
+			    nhdr_l.n_namesz == 0x8 &&
+			    !strcmp(name,"FreeBSD")) {
+				if (elfhdr->e_ident[EI_CLASS] == ELFCLASS32) {
+					raw_size = (uint64_t)*((uint32_t *)
+					    (uintptr_t)(name +
+						ELF_ALIGN((int32_t)
+						nhdr_l.n_namesz, 4) + 8));
+					ver = (uintptr_t)NOTE_OFFSET_32(nhdr,
+					    nhdr_l.n_namesz,0);
+					if (*((int *)ver) == 1)
+						pid = PID32(nhdr,
+						    nhdr_l.n_namesz, 24);
+				} else {
+					raw_size = *((uint64_t *)(uintptr_t)
+					    (name + ELF_ALIGN((int32_t)
+						nhdr_l.n_namesz, 8) + 16));
+					ver = (uintptr_t)NOTE_OFFSET_64(nhdr,
+					    nhdr_l.n_namesz,0);
+					if (*((int *)ver) == 1)
+						pid = PID64(nhdr,
+						    nhdr_l.n_namesz, 40);
+				}
+				xlatetom(elf, elfhdr, &raw_size, &raw_size,
+				    ELF_T_WORD, sizeof(uint64_t));
+				xlatetom(elf, elfhdr, &pid, &pid, ELF_T_WORD,
+				    sizeof(pid_t));
+			}
+
+			if (raw_size != 0 && style == STYLE_SYSV) {
+				(void) snprintf(buf, BUF_SIZE, "%s/%d",
+				    ".reg", pid);
+				tbl_append();
+				tbl_print(buf, 0);
+				tbl_print_num(raw_size, radix, 1);
+				tbl_print_num(0, radix, 2);
+				if (!reg_pseudo) {
+					tbl_append();
+					tbl_print(".reg", 0);
+					tbl_print_num(raw_size, radix, 1);
+					tbl_print_num(0, radix, 2);
+					reg_pseudo = 1;
+					text_size_total += raw_size;
+				}
+				text_size_total += raw_size;
+			}
+		}
+		break;
+		case NT_FPREGSET:	/* same as NT_PRFPREG */
+			if (style == STYLE_SYSV) {
+				(void) snprintf(buf, BUF_SIZE,
+				    "%s/%d", ".reg2", pid);
+				tbl_append();
+				tbl_print(buf, 0);
+				tbl_print_num(nhdr_l.n_descsz, radix, 1);
+				tbl_print_num(0, radix, 2);
+				if (!reg2_pseudo) {
+					tbl_append();
+					tbl_print(".reg2", 0);
+					tbl_print_num(nhdr_l.n_descsz, radix,
+					    1);
+					tbl_print_num(0, radix, 2);
+					reg2_pseudo = 1;
+					text_size_total += nhdr_l.n_descsz;
+				}
+				text_size_total += nhdr_l.n_descsz;
+			}
+			break;
+#if 0
+		case NT_AUXV:
+			if (style == STYLE_SYSV) {
+				tbl_append();
+				tbl_print(".auxv", 0);
+				tbl_print_num(nhdr_l.n_descsz, radix, 1);
+				tbl_print_num(0, radix, 2);
+				text_size_total += nhdr_l.n_descsz;
+			}
+			break;
+		case NT_PRXFPREG:
+			if (style == STYLE_SYSV) {
+				(void) snprintf(buf, BUF_SIZE, "%s/%d",
+				    ".reg-xfp", pid);
+				tbl_append();
+				tbl_print(buf, 0);
+				tbl_print_num(nhdr_l.n_descsz, radix, 1);
+				tbl_print_num(0, radix, 2);
+				if (!regxfp_pseudo) {
+					tbl_append();
+					tbl_print(".reg-xfp", 0);
+					tbl_print_num(nhdr_l.n_descsz, radix,
+					    1);
+					tbl_print_num(0, radix, 2);
+					regxfp_pseudo = 1;
+					text_size_total += nhdr_l.n_descsz;
+				}
+				text_size_total += nhdr_l.n_descsz;
+			}
+			break;
+		case NT_PSINFO:
+#endif
+		case NT_PRPSINFO: {
+			/* FreeBSD 64-bit */
+			if (nhdr_l.n_descsz == 0x78 &&
+				!strcmp(name,"FreeBSD")) {
+				*cmd_line = strdup(NOTE_OFFSET_64(nhdr,
+				    nhdr_l.n_namesz, 33));
+			/* FreeBSD 32-bit */
+			} else if (nhdr_l.n_descsz == 0x6c &&
+				!strcmp(name,"FreeBSD")) {
+				*cmd_line = strdup(NOTE_OFFSET_32(nhdr,
+				    nhdr_l.n_namesz, 25));
+			}
+			/* Strip any trailing spaces */
+			if (*cmd_line != NULL) {
+				char *s;
+
+				s = *cmd_line + strlen(*cmd_line);
+				while (s > *cmd_line) {
+					if (*(s-1) != 0x20) break;
+					s--;
+				}
+				*s = 0;
+			}
+			break;
+		}
+#if 0
+		case NT_PSTATUS:
+		case NT_LWPSTATUS:
+#endif
+		default:
+			break;
+		}
+		NEXT_NOTE(elfhdr, nhdr_l.n_descsz, nhdr_l.n_namesz, offset);
+	}
+}
+
+/*
+ * Handles program headers except for PT_NOTE, when sysv output style is
+ * chosen, prints out the segment name and length. For berkely output
+ * style only PT_LOAD segments are handled, and text,
+ * data, bss size is calculated for them.
+ */
+static void
+handle_phdr(Elf *elf, GElf_Ehdr *elfhdr, GElf_Phdr *phdr,
+    uint32_t idx, const char *name)
+{
+	uint64_t addr, size;
+	int split;
+	char buf[BUF_SIZE];
+
+	if (elf == NULL || elfhdr == NULL || phdr == NULL)
+		return;
+
+	split = (phdr->p_memsz > 0) && 	(phdr->p_filesz > 0) &&
+	    (phdr->p_memsz > phdr->p_filesz);
+
+	if (style == STYLE_SYSV) {
+		(void) snprintf(buf, BUF_SIZE,
+		    "%s%d%s", name, idx, (split ? "a" : ""));
+		tbl_append();
+		tbl_print(buf, 0);
+		tbl_print_num(phdr->p_filesz, radix, 1);
+		tbl_print_num(phdr->p_vaddr, radix, 2);
+		text_size_total += phdr->p_filesz;
+		if (split) {
+			size = phdr->p_memsz - phdr->p_filesz;
+			addr = phdr->p_vaddr + phdr->p_filesz;
+			(void) snprintf(buf, BUF_SIZE, "%s%d%s", name,
+			    idx, "b");
+			text_size_total += phdr->p_memsz - phdr->p_filesz;
+			tbl_append();
+			tbl_print(buf, 0);
+			tbl_print_num(size, radix, 1);
+			tbl_print_num(addr, radix, 2);
+		}
+	} else {
+		if (phdr->p_type != PT_LOAD)
+			return;
+		if ((phdr->p_flags & PF_W) && !(phdr->p_flags & PF_X)) {
+			data_size += phdr->p_filesz;
+			if (split)
+				data_size += phdr->p_memsz - phdr->p_filesz;
+		} else {
+			text_size += phdr->p_filesz;
+			if (split)
+				text_size += phdr->p_memsz - phdr->p_filesz;
+		}
+	}
+}
+
+/*
+ * Given a core dump file, this function maps program headers to segments.
+ */
+static int
+handle_core(char const *name, Elf *elf, GElf_Ehdr *elfhdr)
+{
+	GElf_Phdr phdr;
+	uint32_t i;
+	char *core_cmdline;
+	const char *seg_name;
+
+	if (name == NULL || elf == NULL || elfhdr == NULL)
+		return (RETURN_DATAERR);
+	if  (elfhdr->e_shnum != 0 || elfhdr->e_type != ET_CORE)
+		return (RETURN_DATAERR);
+
+	seg_name = core_cmdline = NULL;
+	if (style == STYLE_SYSV)
+		sysv_header(name, NULL);
+	else
+		berkeley_header();
+
+	for (i = 0; i < elfhdr->e_phnum; i++) {
+		if (gelf_getphdr(elf, i, &phdr) != NULL) {
+			if (phdr.p_type == PT_NOTE) {
+				handle_phdr(elf, elfhdr, &phdr, i, "note");
+				handle_core_note(elf, elfhdr, &phdr,
+				    &core_cmdline);
+			} else {
+				switch(phdr.p_type) {
+				case PT_NULL:
+					seg_name = "null";
+					break;
+				case PT_LOAD:
+					seg_name = "load";
+					break;
+				case PT_DYNAMIC:
+					seg_name = "dynamic";
+					break;
+				case PT_INTERP:
+					seg_name = "interp";
+					break;
+				case PT_SHLIB:
+					seg_name = "shlib";
+					break;
+				case PT_PHDR:
+					seg_name = "phdr";
+					break;
+				case PT_GNU_EH_FRAME:
+					seg_name = "eh_frame_hdr";
+					break;
+				case PT_GNU_STACK:
+					seg_name = "stack";
+					break;
+				default:
+					seg_name = "segment";
+				}
+				handle_phdr(elf, elfhdr, &phdr, i, seg_name);
+			}
+		}
+	}
+
+	if (style == STYLE_BERKELEY) {
+		if (core_cmdline != NULL) {
+			berkeley_footer(core_cmdline, name,
+			    "core file invoked as");
+		} else {
+			berkeley_footer(core_cmdline, name, "core file");
+		}
+	} else {
+		sysv_footer();
+		if (core_cmdline != NULL) {
+			(void) printf(" (core file invoked as %s)\n\n",
+			    core_cmdline);
+		} else {
+			(void) printf(" (core file)\n\n");
+		}
+	}
+	free(core_cmdline);
+	return (RETURN_OK);
+}
+
+/*
+ * Given an elf object,ar(1) filename, and based on the output style
+ * and radix format the various sections and their length will be printed
+ * or the size of the text, data, bss sections will be printed out.
+ */
+static int
+handle_elf(char const *name)
+{
+	GElf_Ehdr elfhdr;
+	GElf_Shdr shdr;
+	Elf *elf, *elf1;
+	Elf_Arhdr *arhdr;
+	Elf_Scn *scn;
+	Elf_Cmd elf_cmd;
+	int exit_code, fd;
+
+	if (name == NULL)
+		return (RETURN_NOINPUT);
+
+	if ((fd = open(name, O_RDONLY, 0)) < 0)
+		return (RETURN_NOINPUT);
+
+	elf_cmd = ELF_C_READ;
+	elf1 = elf_begin(fd, elf_cmd, NULL);
+	while ((elf = elf_begin(fd, elf_cmd, elf1)) != NULL) {
+		arhdr = elf_getarhdr(elf);
+		if (elf_kind(elf) == ELF_K_NONE && arhdr == NULL) {
+			(void) elf_end(elf);
+			(void) elf_end(elf1);
+			(void) close(fd);
+			return (RETURN_DATAERR);
+		}
+		if (elf_kind(elf) != ELF_K_ELF ||
+		    (gelf_getehdr(elf, &elfhdr) == NULL)) {
+			elf_cmd = elf_next(elf);
+			(void) elf_end(elf);
+			warnx("%s: File format not recognized",
+			    arhdr != NULL ? arhdr->ar_name : name);
+			continue;
+		}
+		/* Core dumps are handled separately */
+		if (elfhdr.e_shnum == 0 && elfhdr.e_type == ET_CORE) {
+			exit_code = handle_core(name, elf, &elfhdr);
+			(void) elf_end(elf);
+			(void) elf_end(elf1);
+			(void) close(fd);
+			return (exit_code);
+		} else {
+			scn = NULL;
+			if (style == STYLE_BERKELEY) {
+				berkeley_header();
+				while ((scn = elf_nextscn(elf, scn)) != NULL) {
+					if (gelf_getshdr(scn, &shdr) != NULL)
+						berkeley_calc(&shdr);
+				}
+			} else {
+				sysv_header(name, arhdr);
+				scn = NULL;
+				while ((scn = elf_nextscn(elf, scn)) != NULL) {
+					if (gelf_getshdr(scn, &shdr) !=	NULL)
+						sysv_calc(elf, &elfhdr, &shdr);
+				}
+			}
+			if (style == STYLE_BERKELEY) {
+				if (arhdr != NULL) {
+					berkeley_footer(name, arhdr->ar_name,
+					    "ex");
+				} else {
+					berkeley_footer(name, NULL, "ex");
+				}
+			} else {
+				sysv_footer();
+			}
+		}
+		elf_cmd = elf_next(elf);
+		(void) elf_end(elf);
+	}
+	(void) elf_end(elf1);
+	(void) close(fd);
+	return (RETURN_OK);
+}
+
+/*
+ * Sysv formatting helper functions.
+ */
+static void
+sysv_header(const char *name, Elf_Arhdr *arhdr)
+{
+
+	text_size_total = 0;
+	if (arhdr != NULL)
+		(void) printf("%s   (ex %s):\n", arhdr->ar_name, name);
+	else
+		(void) printf("%s  :\n", name);
+	tbl_new(3);
+	tbl_append();
+	tbl_print("section", 0);
+	tbl_print("size", 1);
+	tbl_print("addr", 2);
+}
+
+static void
+sysv_calc(Elf *elf, GElf_Ehdr *elfhdr, GElf_Shdr *shdr)
+{
+	char *section_name;
+
+	section_name = elf_strptr(elf, elfhdr->e_shstrndx,
+	    (size_t) shdr->sh_name);
+	if ((shdr->sh_type == SHT_SYMTAB ||
+	    shdr->sh_type == SHT_STRTAB || shdr->sh_type == SHT_RELA ||
+	    shdr->sh_type == SHT_REL) && shdr->sh_addr == 0)
+		return;
+	tbl_append();
+	tbl_print(section_name, 0);
+	tbl_print_num(shdr->sh_size, radix, 1);
+	tbl_print_num(shdr->sh_addr, radix, 2);
+	text_size_total += shdr->sh_size;
+}
+
+static void
+sysv_footer(void)
+{
+	tbl_append();
+	tbl_print("Total", 0);
+	tbl_print_num(text_size_total, radix, 1);
+	tbl_flush();
+	putchar('\n');
+}
+
+/*
+ * berkeley style output formatting helper functions.
+ */
+static void
+berkeley_header(void)
+{
+	static int printed;
+
+	text_size = data_size = bss_size = 0;
+	if (!printed) {
+		tbl_new(6);
+		tbl_append();
+		tbl_print("text", 0);
+		tbl_print("data", 1);
+		tbl_print("bss", 2);
+		if (radix == RADIX_OCTAL)
+			tbl_print("oct", 3);
+		else
+			tbl_print("dec", 3);
+		tbl_print("hex", 4);
+		tbl_print("filename", 5);
+		printed = 1;
+	}
+}
+
+static void
+berkeley_calc(GElf_Shdr *shdr)
+{
+	if (shdr != NULL) {
+		if (!(shdr->sh_flags & SHF_ALLOC))
+			return;
+		if ((shdr->sh_flags & SHF_ALLOC) &&
+		    ((shdr->sh_flags & SHF_EXECINSTR) ||
+		    !(shdr->sh_flags & SHF_WRITE)))
+			text_size += shdr->sh_size;
+		else if ((shdr->sh_flags & SHF_ALLOC) &&
+		    (shdr->sh_flags & SHF_WRITE) &&
+		    (shdr->sh_type != SHT_NOBITS))
+			data_size += shdr->sh_size;
+		else
+			bss_size += shdr->sh_size;
+	}
+}
+
+static void
+berkeley_totals(void)
+{
+	uint64_t grand_total;
+
+	grand_total = text_size_total + data_size_total + bss_size_total;
+	tbl_append();
+	tbl_print_num(text_size_total, radix, 0);
+	tbl_print_num(data_size_total, radix, 1);
+	tbl_print_num(bss_size_total, radix, 2);
+	if (radix == RADIX_OCTAL)
+		tbl_print_num(grand_total, RADIX_OCTAL, 3);
+	else
+		tbl_print_num(grand_total, RADIX_DECIMAL, 3);
+	tbl_print_num(grand_total, RADIX_HEX, 4);
+}
+
+static void
+berkeley_footer(const char *name, const char *ar_name, const char *msg)
+{
+	char buf[BUF_SIZE];
+
+	total_size = text_size + data_size + bss_size;
+	if (show_totals) {
+		text_size_total += text_size;
+		bss_size_total += bss_size;
+		data_size_total += data_size;
+	}
+
+	tbl_append();
+	tbl_print_num(text_size, radix, 0);
+	tbl_print_num(data_size, radix, 1);
+	tbl_print_num(bss_size, radix, 2);
+	if (radix == RADIX_OCTAL)
+		tbl_print_num(total_size, RADIX_OCTAL, 3);
+	else
+		tbl_print_num(total_size, RADIX_DECIMAL, 3);
+	tbl_print_num(total_size, RADIX_HEX, 4);
+	if (ar_name != NULL && name != NULL)
+		(void) snprintf(buf, BUF_SIZE, "%s (%s %s)", ar_name, msg,
+		    name);
+	else if (ar_name != NULL && name == NULL)
+		(void) snprintf(buf, BUF_SIZE, "%s (%s)", ar_name, msg);
+	else
+		(void) snprintf(buf, BUF_SIZE, "%s", name);
+	tbl_print(buf, 5);
+}
+
+
+static void
+tbl_new(int col)
+{
+
+	assert(tb == NULL);
+	assert(col > 0);
+	if ((tb = calloc(1, sizeof(*tb))) == NULL)
+		err(EXIT_FAILURE, "calloc");
+	if ((tb->tbl = calloc(col, sizeof(*tb->tbl))) == NULL)
+		err(EXIT_FAILURE, "calloc");
+	if ((tb->width = calloc(col, sizeof(*tb->width))) == NULL)
+		err(EXIT_FAILURE, "calloc");
+	tb->col = col;
+	tb->row = 0;
+}
+
+static void
+tbl_print(const char *s, int col)
+{
+	int len;
+
+	assert(tb != NULL && tb->col > 0 && tb->row > 0 && col < tb->col);
+	assert(s != NULL && tb->tbl[col][tb->row - 1] == NULL);
+	if ((tb->tbl[col][tb->row - 1] = strdup(s)) == NULL)
+		err(EXIT_FAILURE, "strdup");
+	len = strlen(s);
+	if (len > tb->width[col])
+		tb->width[col] = len;
+}
+
+static void
+tbl_print_num(uint64_t num, enum radix_style rad, int col)
+{
+	char buf[BUF_SIZE];
+
+	(void) snprintf(buf, BUF_SIZE, (rad == RADIX_DECIMAL ? "%ju" :
+	    ((rad == RADIX_OCTAL) ? "0%jo" : "0x%jx")), (uintmax_t) num);
+	tbl_print(buf, col);
+}
+
+static void
+tbl_append(void)
+{
+	int i;
+
+	assert(tb != NULL && tb->col > 0);
+	tb->row++;
+	for (i = 0; i < tb->col; i++) {
+		tb->tbl[i] = realloc(tb->tbl[i], sizeof(*tb->tbl[i]) * tb->row);
+		if (tb->tbl[i] == NULL)
+			err(EXIT_FAILURE, "realloc");
+		tb->tbl[i][tb->row - 1] = NULL;
+	}
+}
+
+static void
+tbl_flush(void)
+{
+	const char *str;
+	int i, j;
+
+	if (tb == NULL)
+		return;
+
+	assert(tb->col > 0);
+	for (i = 0; i < tb->row; i++) {
+		if (style == STYLE_BERKELEY)
+			printf("  ");
+		for (j = 0; j < tb->col; j++) {
+			str = (tb->tbl[j][i] != NULL ? tb->tbl[j][i] : "");
+			if (style == STYLE_SYSV && j == 0)
+				printf("%-*s", tb->width[j], str);
+			else if (style == STYLE_BERKELEY && j == tb->col - 1)
+				printf("%s", str);
+			else
+				printf("%*s", tb->width[j], str);
+			if (j == tb->col -1)
+				putchar('\n');
+			else
+				printf("   ");
+		}
+	}
+
+	for (i = 0; i < tb->col; i++) {
+		for (j = 0; j < tb->row; j++) {
+			if (tb->tbl[i][j])
+				free(tb->tbl[i][j]);
+		}
+		free(tb->tbl[i]);
+	}
+	free(tb->tbl);
+	free(tb->width);
+	free(tb);
+	tb = NULL;
+}
+
+#define	USAGE_MESSAGE	"\
+Usage: %s [options] file ...\n\
+  Display sizes of ELF sections.\n\n\
+  Options:\n\
+  --format=format    Display output in specified format.  Supported\n\
+                     values are `berkeley' and `sysv'.\n\
+  --help             Display this help message and exit.\n\
+  --radix=radix      Display numeric values in the specified radix.\n\
+                     Supported values are: 8, 10 and 16.\n\
+  --totals           Show cumulative totals of section sizes.\n\
+  --version          Display a version identifier and exit.\n\
+  -A                 Equivalent to `--format=sysv'.\n\
+  -B                 Equivalent to `--format=berkeley'.\n\
+  -V                 Equivalent to `--version'.\n\
+  -d                 Equivalent to `--radix=10'.\n\
+  -h                 Same as option --help.\n\
+  -o                 Equivalent to `--radix=8'.\n\
+  -t                 Equivalent to option --totals.\n\
+  -x                 Equivalent to `--radix=16'.\n"
+
+static void
+usage(void)
+{
+	(void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
+	exit(EXIT_FAILURE);
+}
+
+static void
+show_version(void)
+{
+	(void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version());
+	exit(EXIT_SUCCESS);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/strings/Makefile	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,11 @@
+# $Id: Makefile 2044 2011-10-23 14:52:59Z jkoshy $
+
+TOP=	..
+
+PROG=   strings
+WARNS?= 6
+DPADD=	${LIBELFTC} ${LIBELF}
+LDADD=  -lelftc -lelf
+
+.include "${TOP}/mk/elftoolchain.prog.mk"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/strings/os.NetBSD.mk	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,2 @@
+# TODO(#511): Revert after the source tree is -Wconversion clean.
+WARNS=5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/strings/strings.1	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,165 @@
+.\" Copyright (c) 2007 S.Sam Arun Raj
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: strings.1 3360 2016-01-24 18:34:06Z jkoshy $
+.\"
+.Dd January 24, 2016
+.Dt STRINGS 1
+.Os
+.Sh NAME
+.Nm strings
+.Nd "print the strings of printable characters in files"
+.Sh SYNOPSIS
+.Nm
+.Op Fl a | Fl -all
+.Op Fl e Ar encoding | Fl -encoding= Ns Ar encoding
+.Op Fl f | Fl -print-file-name
+.Op Fl h | Fl -help
+.Op Fl n Ar number | Fl -bytes= Ns Ar number | Fl Ar number
+.Op Fl o
+.Op Fl t Ar radix | Fl -radix= Ns Ar radix
+.Op Fl v | Fl -version
+.Op Ar
+.Sh DESCRIPTION
+For each
+.Ar file
+specified, the
+.Nm
+utility prints contiguous sequences of printable
+characters that are at least
+.Va n
+characters long and are followed by an unprintable character.
+The default value of
+.Va n
+is 4.
+By default, the
+.Nm
+utility only scans the initialized and loaded sections of ELF objects;
+for other file types, the entire file is scanned.
+The
+.Nm
+utility is mainly used for determining the contents of non-text files.
+.Pp
+If no file name is specified as an argument, standard input is read.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl a | Fl -all
+For ELF objects, scan the entire file for printable strings.
+.It Fl e Ar encoding | Fl -encoding= Ns Ar encoding
+Select the character encoding to be used while searching for strings.
+Valid values for argument
+.Ar encoding
+are:
+.Bl -tag -width indent -compact
+.It Ar s
+for single 7-bit-byte characters (ASCII, ISO 8859).
+.It Ar S
+for single 8-bit-byte characters.
+.It Ar l
+for 16-bit little-endian.
+.It Ar b
+for 16-bit big-endian.
+.It Ar L
+for 32-bit little-endian.
+.It Ar B
+for 32-bit big-endian.
+.El
+The default is to assume that characters are encoded using a single
+7-bit byte.
+.It Fl f | Fl -print-file-name
+Print the name of the file before each string.
+.It Fl h | Fl -help
+Print a usage summary and exit.
+.It Xo
+.Fl n Ar number |
+.Fl -bytes= Ns Ar number |
+.Fl Ar number
+.Xc
+Print the contiguous character sequence of at least
+.Ar number
+characters long, instead of the default of 4 characters.
+Argument
+.Ar number
+should specify a positive decimal integer.
+.It Fl o
+Equivalent to specifying
+.Fl t Ar o .
+.It Fl t Ar radix | Fl -radix= Ns Ar radix
+Print the offset from the start of the file before each string
+using the specified radix.
+Valid values for argument
+.Ar radix
+are:
+.Bl -tag -width indent -compact
+.It Ar d
+for decimal
+.It Ar o
+for octal
+.It Ar x
+for hexadecimal
+.El
+.It Fl v | Fl -version
+Display a version identifier and exit.
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+To display strings in
+.Pa /bin/ls
+use:
+.Dl "$ strings /bin/ls"
+.Pp
+To display strings in all sections of
+.Pa /bin/ln
+use:
+.Dl "$ strings -a /bin/ln"
+.Pp
+To display strings in all sections of
+.Pa /bin/cat
+prefixed with the filename and the offset within the file use:
+.Dl "$ strings -a -f -t x /bin/cat"
+.Sh SEE ALSO
+.Xr ar 1 ,
+.Xr nm 1 ,
+.Xr objdump 1 ,
+.Xr ranlib ,
+.Xr readelf 1 ,
+.Xr size 1
+.Sh HISTORY
+The first FreeBSD
+.Nm
+utility appeared in
+.Fx v3.
+It was later discontinued in
+.Fx v5 ,
+when i386-only a.out format was dropped in favor of ELF.
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+utility was re-written by
+.An S.Sam Arun Raj Aq Mt samarunraj@gmail.com .
+This manual page was written by
+.An S.Sam Arun Raj Aq Mt samarunraj@gmail.com .
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/strings/strings.c	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,448 @@
+/*-
+ * Copyright (c) 2007 S.Sam Arun Raj
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include <libelf.h>
+#include <libelftc.h>
+#include <gelf.h>
+
+#include "_elftc.h"
+
+ELFTC_VCSID("$Id: strings.c 3571 2017-09-14 02:04:50Z emaste $");
+
+enum radix_style {
+	RADIX_DECIMAL,
+	RADIX_HEX,
+	RADIX_OCTAL
+};
+
+enum encoding_style {
+	ENCODING_7BIT,
+	ENCODING_8BIT,
+	ENCODING_16BIT_BIG,
+	ENCODING_16BIT_LITTLE,
+	ENCODING_32BIT_BIG,
+	ENCODING_32BIT_LITTLE
+};
+
+#define PRINTABLE(c)						\
+      ((c) >= 0 && (c) <= 255 &&				\
+	  ((c) == '\t' || isprint((c)) ||			\
+	      (encoding == ENCODING_8BIT && (c) > 127)))
+
+static int encoding_size, entire_file, show_filename, show_loc;
+static enum encoding_style encoding;
+static enum radix_style radix;
+static intmax_t min_len;
+
+static struct option strings_longopts[] = {
+	{ "all",		no_argument,		NULL,	'a'},
+	{ "bytes",		required_argument,	NULL,	'n'},
+	{ "encoding",		required_argument,	NULL,	'e'},
+	{ "help",		no_argument,		NULL,	'h'},
+	{ "print-file-name",	no_argument,		NULL,	'f'},
+	{ "radix",		required_argument,	NULL,	't'},
+	{ "version",		no_argument,		NULL,	'v'},
+	{ NULL, 0, NULL, 0 }
+};
+
+long	getcharacter(void);
+int	handle_file(const char *);
+int	handle_elf(const char *, int);
+int	handle_binary(const char *, int);
+int	find_strings(const char *, off_t, off_t);
+void	show_version(void);
+void	usage(void);
+
+/*
+ * strings(1) extracts text(contiguous printable characters)
+ * from elf and binary files.
+ */
+int
+main(int argc, char **argv)
+{
+	int ch, rc;
+
+	rc = 0;
+	min_len = 0;
+	encoding_size = 1;
+	if (elf_version(EV_CURRENT) == EV_NONE)
+		errx(EXIT_FAILURE, "ELF library initialization failed: %s",
+		    elf_errmsg(-1));
+
+	while ((ch = getopt_long(argc, argv, "1234567890ae:fhn:ot:Vv",
+	    strings_longopts, NULL)) != -1) {
+		switch ((char)ch) {
+		case 'a':
+			entire_file = 1;
+			break;
+		case 'e':
+			if (*optarg == 's') {
+				encoding = ENCODING_7BIT;
+			} else if (*optarg == 'S') {
+				encoding = ENCODING_8BIT;
+			} else if (*optarg == 'b') {
+				encoding = ENCODING_16BIT_BIG;
+				encoding_size = 2;
+			} else if (*optarg == 'B') {
+				encoding = ENCODING_32BIT_BIG;
+				encoding_size = 4;
+			} else if (*optarg == 'l') {
+				encoding = ENCODING_16BIT_LITTLE;
+				encoding_size = 2;
+			} else if (*optarg == 'L') {
+				encoding = ENCODING_32BIT_LITTLE;
+				encoding_size = 4;
+			} else
+				usage();
+			        /* NOTREACHED */
+			break;
+		case 'f':
+			show_filename = 1;
+			break;
+		case 'n':
+			min_len = strtoimax(optarg, (char**)NULL, 10);
+			if (min_len <= 0)
+				errx(EX_USAGE, "option -n should specify a "
+				    "positive decimal integer.");
+			break;
+		case 'o':
+			show_loc = 1;
+			radix = RADIX_OCTAL;
+			break;
+		case 't':
+			show_loc = 1;
+			if (*optarg == 'd')
+				radix = RADIX_DECIMAL;
+			else if (*optarg == 'o')
+				radix = RADIX_OCTAL;
+			else if (*optarg == 'x')
+				radix = RADIX_HEX;
+			else
+				usage();
+			        /* NOTREACHED */
+			break;
+		case 'v':
+		case 'V':
+			show_version();
+			/* NOTREACHED */
+		case '0':
+	        case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+		case '8':
+		case '9':
+			min_len *= 10;
+			min_len += ch - '0';
+			break;
+		case 'h':
+		case '?':
+		default:
+			usage();
+			/* NOTREACHED */
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	if (min_len == 0)
+		min_len = 4;
+	if (*argv == NULL)
+		rc = find_strings("{standard input}", 0, 0);
+	else while (*argv != NULL) {
+		if (handle_file(*argv) != 0)
+			rc = 1;
+		argv++;
+	}
+	return (rc);
+}
+
+int
+handle_file(const char *name)
+{
+	int fd, rt;
+
+	if (name == NULL)
+		return (1);
+	if (freopen(name, "rb", stdin) == NULL) {
+		warnx("'%s': %s", name, strerror(errno));
+		return (1);
+	}
+
+	fd = fileno(stdin);
+	if (fd < 0)
+		return (1);
+	rt = handle_elf(name, fd);
+	return (rt);
+}
+
+/*
+ * Files not understood by handle_elf, will be passed off here and will
+ * treated as a binary file. This would include text file, core dumps ...
+ */
+int
+handle_binary(const char *name, int fd)
+{
+	struct stat buf;
+
+	memset(&buf, 0, sizeof(buf));
+	(void)lseek(fd, 0, SEEK_SET);
+	if (!fstat(fd, &buf))
+		return (find_strings(name, 0, buf.st_size));
+	return (1);
+}
+
+/*
+ * Will analyse a file to see if it ELF, other files including ar(1),
+ * core dumps are passed off and treated as flat binary files. Unlike
+ * GNU size in FreeBSD this routine will not treat ELF object from
+ * different archs as flat binary files(has to overridden using -a).
+ */
+int
+handle_elf(const char *name, int fd)
+{
+	GElf_Ehdr elfhdr;
+	GElf_Shdr shdr;
+	Elf *elf;
+	Elf_Scn *scn;
+	int rc;
+
+	rc = 0;
+	/* If entire file is chosen, treat it as a binary file */
+	if (entire_file)
+		return (handle_binary(name, fd));
+
+	(void)lseek(fd, 0, SEEK_SET);
+	elf = elf_begin(fd, ELF_C_READ, NULL);
+	if (elf_kind(elf) != ELF_K_ELF) {
+		(void)elf_end(elf);
+		return (handle_binary(name, fd));
+	}
+
+	if (gelf_getehdr(elf, &elfhdr) == NULL) {
+		(void)elf_end(elf);
+		warnx("%s: ELF file could not be processed", name);
+		return (1);
+	}
+
+	if (elfhdr.e_shnum == 0 && elfhdr.e_type == ET_CORE) {
+		(void)elf_end(elf);
+		return (handle_binary(name, fd));
+	} else {
+		scn = NULL;
+		while ((scn = elf_nextscn(elf, scn)) != NULL) {
+			if (gelf_getshdr(scn, &shdr) == NULL)
+				continue;
+			if (shdr.sh_type != SHT_NOBITS &&
+			    (shdr.sh_flags & SHF_ALLOC) != 0) {
+				rc = find_strings(name, shdr.sh_offset,
+				    shdr.sh_size);
+			}
+		}
+	}
+	(void)elf_end(elf);
+	return (rc);
+}
+
+/*
+ * Retrieves a character from input stream based on the encoding
+ * type requested.
+ */
+long
+getcharacter(void)
+{
+	long rt;
+	int i;
+	char buf[4], c;
+
+	rt = EOF;
+	for(i = 0; i < encoding_size; i++) {
+		c = getc(stdin);
+		if (feof(stdin))
+			return (EOF);
+		buf[i] = c;
+	}
+
+	switch (encoding) {
+	case ENCODING_7BIT:
+	case ENCODING_8BIT:
+		rt = buf[0];
+		break;
+	case ENCODING_16BIT_BIG:
+		rt = (buf[0] << 8) | buf[1];
+		break;
+	case ENCODING_16BIT_LITTLE:
+		 rt = buf[0] | (buf[1] << 8);
+		 break;
+	case ENCODING_32BIT_BIG:
+		rt = ((long) buf[0] << 24) | ((long) buf[1] << 16) |
+		    ((long) buf[2] << 8) | buf[3];
+		break;
+	case ENCODING_32BIT_LITTLE:
+		rt = buf[0] | ((long) buf[1] << 8) | ((long) buf[2] << 16) |
+		    ((long) buf[3] << 24);
+		break;
+	}
+	return (rt);
+}
+
+/*
+ * Input stream stdin is read until the end of file is reached or until
+ * the section size is reached in case of ELF files. Contiguous
+ * characters of >= min_size(default 4) will be displayed.
+ */
+int
+find_strings(const char *name, off_t offset, off_t size)
+{
+	off_t cur_off, start_off;
+	char *obuf;
+	long c;
+	int i;
+
+	if ((obuf = (char*)calloc(1, min_len + 1)) == NULL) {
+		fprintf(stderr, "Unable to allocate memory: %s\n",
+		    strerror(errno));
+		return (1);
+	}
+
+	(void)fseeko(stdin, offset, SEEK_SET);
+	cur_off = offset;
+	start_off = 0;
+	for (;;) {
+		if ((offset + size) && (cur_off >= offset + size))
+			break;
+		start_off = cur_off;
+		memset(obuf, 0, min_len + 1);
+		for(i = 0; i < min_len; i++) {
+			c = getcharacter();
+			if (c == EOF && feof(stdin))
+				goto _exit1;
+			if (PRINTABLE(c)) {
+				obuf[i] = c;
+				obuf[i + 1] = 0;
+				cur_off += encoding_size;
+			} else {
+				if (encoding == ENCODING_8BIT &&
+				    (uint8_t)c > 127) {
+					obuf[i] = c;
+					obuf[i + 1] = 0;
+					cur_off += encoding_size;
+					continue;
+				}
+				cur_off += encoding_size;
+				break;
+			}
+		}
+
+		if (i >= min_len && ((cur_off <= offset + size) ||
+		    !(offset + size))) {
+			if (show_filename)
+				printf("%s: ", name);
+			if (show_loc) {
+				switch (radix) {
+				case RADIX_DECIMAL:
+					printf("%7ju ", (uintmax_t)start_off);
+					break;
+				case RADIX_HEX:
+					printf("%7jx ", (uintmax_t)start_off);
+					break;
+				case RADIX_OCTAL:
+					printf("%7jo ", (uintmax_t)start_off);
+					break;
+				}
+			}
+			printf("%s", obuf);
+
+			for (;;) {
+				if ((offset + size) &&
+				    (cur_off >= offset + size))
+					break;
+				c = getcharacter();
+				cur_off += encoding_size;
+				if (encoding == ENCODING_8BIT &&
+				    (uint8_t)c > 127) {
+					putchar(c);
+					continue;
+				}
+				if (!PRINTABLE(c) || c == EOF)
+					break;
+				putchar(c);
+			}
+			putchar('\n');
+		}
+	}
+_exit1:
+	free(obuf);
+	return (0);
+}
+
+#define	USAGE_MESSAGE	"\
+Usage: %s [options] [file...]\n\
+  Print contiguous sequences of printable characters.\n\n\
+  Options:\n\
+  -a     | --all               Scan the entire file for strings.\n\
+  -e ENC | --encoding=ENC      Select the character encoding to use.\n\
+  -f     | --print-file-name   Print the file name before each string.\n\
+  -h     | --help              Print a help message and exit.\n\
+  -n N   | --bytes=N | -N      Print sequences with 'N' or more characters.\n\
+  -o                           Print offsets in octal.\n\
+  -t R   | --radix=R           Print offsets using the radix named by 'R'.\n\
+  -v     | --version           Print a version identifier and exit.\n"
+
+void
+usage(void)
+{
+
+	fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
+	exit(EXIT_FAILURE);
+}
+
+void
+show_version(void)
+{
+
+        printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version());
+        exit(EXIT_SUCCESS);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/elftoolchain/upstream-version	Fri Nov 30 12:49:04 2018 -0500
@@ -0,0 +1,1 @@
+freebsd git 860efdae73d4967903f45d878f53480bb05ff66c